tags:

views:

125

answers:

3

Hi friends,

I have created a table. In one field, I have a priority of that record (between 1-9). I didn't set priority for all the records, so for some records, it will remain null.

When displaying these records in my HTML page, I just check those priorities -- if the priority exists, then I will display as it is, if it's null, then I will display it as the lowest priority of '10' (just for display).

The problem occurs while sorting the table. If I try to sort(DESC) the table, it displays the 10 in the first row and later continues perfectly (1,2,....).

How to solve this?

Is it possible to display the priorities first and later continue with the null values?

+4  A: 

Here's a short sample that shows how to convert NULL's into a value and then sort on it..

create table test
(
    priority int null,
    detail varchar(10)
)

insert into test values (1, 'one')
insert into test values (3, 'three')
insert into test values (8, 'eight')
insert into test values (9, 'nine')
insert into test values (null, 'ten')

select ISNULL(priority, 10), detail from test order by ISNULL(priority, 10)

The key is ISNULL'ing the null'able value field to convert NULL's to the value (10) that you want.

Rob
This is fine for smaller tables, just be aware the per-row functions do not scale well.
paxdiablo
In the nicest possible sense, "rubbish" -- I've worked on a system where there've been null's in tables that are considerably wider and considerably longer (c. 5+million records) and performance has been more than adequate (That includes the data being used in complex joining queries). That was with Sql Server 2000, I'd imagine 2k5/2k8 would be as good, if not better. MySql on the other hand - well, it does little well, so who knows ;-)
Rob
I've just performed a micro-benchmark on this (2 column table, 655k rows, 20% with priority as null, 80% equal split between [1,3,8,9}) and over 4 executions of each, there was no significant difference in performance.
Rob
+1 Simple solution and it works well. I also don't think Pax's comment is relevant - do you ever display the full content of a large table? On a web page? I've never had an issue with isnull's performance, but that wouldn't be an issue in this case if there were.
Cobus Kruger
Five million rows is not a big table. It may be for your PC-type databases but that's probably at the high end of a small table on the mainframe. And I was careful not to say your answer was wrong since it depends entirely on how large the tables are expected to get. Myself, I prefer to give answers targeted towards the more general case which is why I didn't comment of MySQL.
paxdiablo
So in the general case you should merrily replace "null" (which has a meaning of value unknown/not specified) with "10" and break a fairly fundamental rule of database design? Oh - 5million was an example, not a hard and fast rule. Either way, replacing null with a hard-coded "magic number" in the database itself is wrong, wrong, wrong.
Rob
No, not something I'd do in the general case, just this specific one. The questioner stated that the only values were {1-9,NULL} which allows for optimizations based on the data. I agree with the general rule that NULLs should be used for unknown values but my preference is always for pragmatism over dogmatism...
paxdiablo
The use of 10 solves the sorting problem easily and loses nothing in performance since an "IS NULL" is no faster than an "= 10" in any DBMS I've worked in. And if, for some reason in the future, they want to used level 10, it's an easy fix to bump the current 10s up to a higher value without losing information whilst still maintaining sort order.
paxdiablo
You may think I'm wrong. That's certainly possible, you wouldn't be the only one. But the ability to toss out the rulebook when it gets in the way of solution delivery is a valuable one in my opinion. Now, it may be that your solution is fine for MySQL as well as SQLServer (that you benchmarked). Fine, use it, problem solved. But I've seen the sort of performance that per-row functions can get in SELECTs and I'm always wary of them.
paxdiablo
If you really wanted to maintain schema integrity, you could keep the NULLs in the table and do two queries (one for NULLs and one for NOT NULLs) without having to use per-row functions. Not *everything* has to be in a single SQL query, something people sometimes forget.
paxdiablo
Anyway, that's my two cents worth (and you may even think *that's* over-valued).
paxdiablo
+2  A: 

There are a number of ways to solve it.

1/ Change the data so that 10 is actually in the table (rather than NULL):

update table TBL set FLD = 10 where FLD is null;

2/ Modify your query to return different values for NULL:

select FLD1, FLD2, case where FLD3 is null then 10 else FLD3 end from ...

3/ Create a view to do option 2 above automagically.

I'd tend to go for option 1 since it's likely to be the most efficient.

SQL does not specify how NULLs are sorted (although I think it specifies they must be adjacent) - that means they could be at the beginning or end (or possibly in the middle though I've never seen that happen).

The reason I bring up the efficiency aspect is that per-row functions do not scale well. As the table gets bigger, you'll find that converting NULLs into 10 every time you select will be very expensive.

It's far better to bite the bullet and just set them to 10 in the database. This will allow the DBMS to optimize queries better. And, if you ever need to use 10 for another real priority level, just change all the current 10s to 11s (or 9999s) before you start.

paxdiablo
+1  A: 

If you want records with NULL priority to appear last, I would recommend something like

ORDER BY (IFNULL(Priority, 1000000)) or something like this

Bogdan_Ch
The users will eventually insert records with priority 1000001. I'd do it with `ORDER BY CASE WHEN Priority IS NULL THEN 1 ELSE 0 END, Priority` just to be sure.
wqw