tags:

views:

228

answers:

4

A bit of a strange one, I want to write a MySQL query that will get results from a table, but prefer one value of a column over another, ie

id   name    value   prioirty
1    name1   value1  NULL
2    name1   value1  1
3    name2   value2  NULL
4    name3   value3  NULL

So here name1 has two entries, but one has a prioirty of 1. I want to get all the values from the table, but prefer the values with whatever priorty I'm after.

The results I'd be after would be

id   name    value   prioirty
2    name1   value1  1
3    name2   value2  NULL
4    name3   value3  NULL

An equivalent way of saying it would be 'get all rows from the table, but prefer rows with a priority of x'.

A: 

Maybe something like:

SELECT id, name, value, priority FROM 
table_name GROUP BY name ORDER BY priority

Although not having a database in front of me I can't test it...

vitch
A: 

You need to redesign your table first.

It should be:

YourTable (Id, Name, Value)
YourTablePriority (PriorityId, Priority, Id)

Update:

select * from YourTable a 
where a.Id not in 
   (select b.Id from YourTablePriority b)

This should work in sql server, you may need a little change to make it work in mysql.

Colour Blend
What's the point? And what difference would it make to the soultion?
Gaz
Your table will be normalized and there will be no NULL values
Colour Blend
It will also remove the duplicate name1 and value1
Colour Blend
You will then be able to select all names with no priorities in the the priority table.
Colour Blend
+1  A: 

This should do it:

SELECT
     T1.id,
     T1.name,
     T1.value,
     T1.priority
FROM
     My_Table T1
LEFT OUTER JOIN My_Table T2 ON
     T2.name = T1.name AND
     T2.priority > COALESCE(T1.priority, -1)
WHERE
     T2.id IS NULL

This also allows you to have multiple priority levels with the highest being the one that you want to return (if you had a 1 and 2, the 2 would be returned).

I will also say though that it does seem like there are some design problems in the DB. My approach would have been:

My_Table (id, name) My_Values (id, priority, value) with an FK on id to id. PKs on id in My_Table and id, priority in My_Values. Of course, I'd use appropriate table names too.

Tom H.
@Tom, when I run this I on Gary's data set, I get results for only "name2" and "name3" -- the interesting case is excluded because the WHERE clause is false wherever T2.priority is actually defined...
pilcrow
Whoops... the >= should just be >. I'll fix that.
Tom H.
A: 

If I understand correctly, you want the value of a name given a specific priority, or the value associated with a NULL priority. (You do not necessarily want the MAX(priority) that exists.)

Yes, you've got some awkward design issues which you should address, but let's solve the problem you do have at present (and you can later migrate to the problem you ought to have :) ):

mysql> SET @priority = 1;  -- the priority we want, if recorded

mysql> PREPARE stmt FROM "
       SELECT
         t0.*
       FROM
         t t0
       LEFT JOIN
         (SELECT DISTINCT name, priority FROM t WHERE priority = ?) t1
           ON t0.name = t1.name
       WHERE
         t0.priority = t1.priority
           OR
         t1.priority IS NULL
       ";

mysql> EXECUTE stmt USING @priority;
+----+-------+--------+----------+
| id | name  | value  | priority |
+----+-------+--------+----------+
|  2 | name1 | valueX |        1 | 
|  3 | name2 | value2 |     NULL | 
|  4 | name3 | value3 |     NULL | 
+----+-------+--------+----------+
3 rows in set (0.00 sec)

(Note that I changed the prioritized value of "name1" to "valueX" in the above -- your original formulation had identical value values for "name1" regardless of priority, which made it hard for me to understand why you cared to discriminate one from the other.)

pilcrow