根据优先级选择查询选择

时间:2010-08-20 20:06:22

标签: sql sql-server sql-server-2005 tsql

有人请更改我的标题,以更好地反映我想要问的内容。

我有一张像

这样的表格
Table (id, value, value_type, data)

ID不是唯一的。没有唯一的密钥。

value_type有两个可能的值,比方说A和B.

B型优于A,但通常不可用。

对于每个id,如果存在value_type B的任何记录,我希望所有具有该id和value_type B的记录。

如果没有带有value_Type B的id的记录,我想要所有带有id和value_type A的记录。

请注意,如果该ID存在B,我不希望记录类型为A。

我目前使用一系列临时表来执行此操作。是否有单个select语句(子查询OK)可以完成这项工作?

非常感谢!

其他详细信息:

SQL Server 2005

7 个答案:

答案 0 :(得分:5)

RANK,而非ROW_NUMBER,因为您希望关联(具有相同B值的关系)具有相同的排名值:

WITH summary AS (
  SELECT t.*,
         RANK() OVER (PARTITION BY t.id 
                          ORDER BY t.value_type DESC) AS rank
    FROM TABLE t
   WHERE t.value_type IN ('A', 'B'))
SELECT s.id,
       s.value,
       s.value_type,
       s.data
  FROM summary s
 WHERE s.rank = 1

非CTE版本:

SELECT s.id,
       s.value,
       s.value_type,
       s.data
  FROM (SELECT t.*,
               RANK() OVER (PARTITION BY t.id 
                                ORDER BY t.value_type DESC) AS rank
          FROM TABLE t
         WHERE t.value_type IN ('A', 'B')) s
 WHERE s.rank = 1

WITH test AS (
   SELECT 1 AS id, 'B' AS value_type
   UNION ALL
   SELECT 1, 'B'
   UNION ALL
   SELECT 1, 'A'
   UNION ALL
   SELECT 2, 'A'
   UNION ALL
   SELECT 2, 'A'),
     summary AS (
   SELECT t.*,
          RANK() OVER (PARTITION BY t.id 
                           ORDER BY t.value_type DESC) AS rank
     FROM test t)
SELECT *
  FROM summary
 WHERE rank = 1

我明白了:

id   value_type  rank
----------------------
1    B           1
1    B           1
2    A           1
2    A           1

答案 1 :(得分:3)

SELECT * 
  FROM table 
 WHERE value_type = B
UNION ALL
SELECT * 
  FROM table 
 WHERE ID not in (SELECT distinct id 
                    FROM table 
                   WHERE value_type = B)

答案 2 :(得分:2)

我能想到的最短的查询:

SELECT TOP 1 WITH TIES *
FROM #test
ORDER BY Rank() OVER (PARTITION BY id ORDER BY value_type DESC)

这与OMG Ponies和Christoperous 5000的解决方案在CPU上差不多50%,但读取次数相同。这是额外的排序,它需要更多的CPU。

到目前为止,我提出的表现最佳的原始查询是:

SELECT * 
FROM #test 
WHERE value_type = 'B'
UNION ALL
SELECT * 
FROM #test T1
WHERE NOT EXISTS (
   SELECT *
   FROM #test T2
   WHERE
      T1.id = T2.id
      AND T2.value_type = 'B'
)

这始终比CPU上显示的所有其他人大约1/3(其他人大约多50%),但读取次数是3倍。此查询的持续时间通常是所有其他查询的时间的2/3。我认为这是一个很好的竞争者。

索引和数据类型可能会改变一切。

答案 3 :(得分:1)

declare @test as table(
 id int , value [nvarchar](255),value_type [nvarchar](255),data  int)

 INSERT INTO @test
 SELECT 1, 'X', 'A',1 UNION
 SELECT 1, 'X', 'A',2 UNION
 SELECT 1, 'X', 'A',3 UNION
 SELECT 1, 'X', 'A',4 UNION
 SELECT 2, 'X', 'A',5 UNION
 SELECT 2, 'X', 'B',6 UNION
 SELECT 2, 'X', 'B',7 UNION
 SELECT 2, 'X', 'A',8 UNION
 SELECT 2, 'X', 'A',9 


 SELECT * FROM @test x
 INNER JOIN 
 (SELECT id, MAX(value_type) as value_type FROM 
 @test GROUP BY id) as y
 ON x.id = y.id AND x.value_type = y.value_type

答案 4 :(得分:0)

这使用了一个union,它将值B的所有记录与只有A值的所有记录组合在一起:

SELECT *
FROM mainTable
WHERE value_type = B
GROUP BY value_type UNION SELECT *
                          FROM mainTable
                          WHERE value_type = A
                               AND id NOT IN(SELECT *
                                             FROM mainTable
                                             WHERE value_type = B);

答案 5 :(得分:0)

试试这个(MSSQL)。

Select id, value_typeB, null
from myTable
where value_typeB is not null
Union All
Select id, null, value_typeA
from myTable
where value_typeB is null and value_typeA is not null

答案 6 :(得分:0)

也许是这样的:

select * from mytable
where id in (select distinct id where value_type = "B")
union
select * from mytable
where id in (select distinct id where value_type = "A" 
and id not in (select distinct id where value_type = "B"))