2013-03-04 5 views
2

Я делаю союз как такSQL союза удалить «пол-дубликаты»

select name, price from products where project = 10 // prio 1 
union 
select name, price from products where customer = 5 // prio 2 
union 
select name, price from products where standard = 9 // prio 3 

редактирование: изменил где-положение, чтобы сделать его немного более сложным

это, как правило, дает me back

+-----+------+-----------+--------------+ 
|(NO) | name | price | (prio)  | 
+-----+------+-----------+--------------+ 
| 1 | a | 10  | (1)   | 
| 2 | b |  5  | (1)   | 

| 3 | a | 13  | (2)   | 
| 4 | b |  2  | (2)   | 

| 5 | a |  1  | (3)   | 
| 6 | b |  5  | (3)   | 
| 7 | c |  3  | (3)   | 
+-----+------+-----------+--------------+ 

Я понимаю, что, например, строки № 1 и 3 не являются дубликатами и не будут удалены с помощью инструкции union. Однако это именно то, что я хочу сделать. То есть, если имя (например, «a») возвращается первым оператором select (prio 1), я не хочу, чтобы другие «a»: s попадали в набор результатов из операторов выбора с более высоким приоритетом.

т.е., я хочу это:

+-----+------+-----------+--------------+ 
|(NO) | name | price | (prio) | 
+-----+------+-----------+--------------+ 
| 1 | a | 10  | (1)   | 
| 2 | b |  5  | (1)   | 

| 7 | c |  3  | (3)   | 
+-----+------+-----------+--------------+ 

возможно ли это?

Я попытался с помощью group by, но это требует от меня использовать MIN, MAX, AVG и т.д. на цену, которую я не хочу делать, а именно:

select name, avg(price) from (...original query...) group by name 
// this is not ok since I donnot want the avg price, I want the "first" price 

Я использую MS SQL 2000. Могу ли я использовать что-то вроде first(..) как функцию агрегата в group by? При попытке этого я получаю сообщение об ошибке:

select name, first(price) from (...original query...) group by name 
// error: 'first' is not a recognized built-in function name. 

Спасибо!

+1

Что [РСУБД] (http://en.wikipedia.org/wiki/Relational_database_management_system) вы используете? 'RDBMS' означает * Реляционная система управления базами данных *. 'RDBMS является основой для SQL' и для всех современных систем баз данных, таких как MS SQL Server, IBM DB2, Oracle, MySQL и т. Д. –

+0

@JW. Я вижу, что у вас есть ответ SQL Server, готовый к работе. Он отсутствует 'WHERE prio IN (1, 2, 3)' –

+0

@MartinSmith, но я думаю, что он выиграл; t работает в 'SQL Server 2000' hehe –

ответ

2

Для SQL Server 2005+:

WITH records 
AS 
(
    SELECT name, price, prio, 
      ROW_NUMBER() OVER (PARTITION BY name 
           ORDER BY prio ASC) rn 
    FROM products 
) 
SELECT Name, Price 
FROM records 
WHERE rn = 1 

Try это для SQL Server 2000:

SELECT a.* 
FROM products a 
     INNER JOIN 
     (
      SELECT name, MIN(prio) min_prio 
      FROM products 
      WHERE prio IN (1,2,3) 
      GROUP BY name 
     ) b ON a.name = b.name AND 
       a.prio = b.min_prio 

для повышения производительности добавьте индекс соединения в столбце (name, prio).

+0

Спасибо JW., Это выглядит великолепно! НО, мне жаль, что эта проблема слишком упростилась. Если вы не разочарованы, взгляните на новые предложения where-clauses в квесте :) – Cotten

1
select name, price from products where prio = 1 
union 
select name, price from products where prio = 2 and name not in (select name from products where prio = 1) 

union 
select name, price from products where prio = 3 and name not in 
(select name from products where prio = 1 
union 
select name from products where prio = 2 and name not in (select name from products where prio = 1)) 
1

Не уверен, если это работает, но идея такова:

select name, 
    min(case when prio=min_prio then price else NULL end) as price, 
    min(prio) as min_prio 
from products 
group by name 
order by min_prio 
Смежные вопросы