坚持这个联盟/除了

时间:2011-10-06 14:21:26

标签: sql sql-server

试图找到继续这个的最好方法,出于某种原因,它真的让我感到沮丧。

我有这样的数据:

transaction_id(pk)  decision_id(pk)   accepted_ind    
A                    1                NULL
A                    2                <blank>
A                    4                Y
B                    1                <blank>
B                    2                Y
C                    1                Y
D                    1                N
D                    2                O
D                    3                Y
  1. 每笔交易都保证有决定1
  2. 可能存在多种决策可能性(假设的)场景类型
  3. 接受可以有多个值,或者为空或NULL,但只能有一个可以接受_ind = Y
  4. 我正在尝试将查询写入:

    1. 为每个transaction_id
    2. 返回一行
    3. 返回requested_ind = Y或者事务没有行accepted_ind = Y的decision_id,然后返回decision_id = 1的行(不管accepted_ind中的值是什么)
    4. 我试过了: 1.使用逻辑“或”来拉取记录,不断重复。 2.使用联合但除了但不能完全正确地降低逻辑。

      感谢任何帮助。我不知道为什么这会让我如此沮丧!

      亚当

4 个答案:

答案 0 :(得分:2)

试试这个。基本上WHERE条款说:

接受的地方='Y' OR
此事务没有可接受的行,decision_id = 1

SELECT Transaction_id, Decision_ID, Accepted_id
FROM MyTable t
WHERE Accepted_ind = 'Y'
OR (NOT EXISTS (SELECT 1 FROM MyTable t2
                WHERE Accepted_ind = 'Y'
                and t2.Transaction_id = t.transaction_id)
    AND Decision_id = 1)

答案 1 :(得分:2)

此方法使用ROW_NUMBER(),因此仅适用于SQL Server 2005或更高版本

我已按原样修改了您的示例数据,所有transaction_id都有一个Y指标!

DECLARE @t TABLE ( 
    transaction_id NCHAR(1), 
    decision_id INT, 
    accepted_ind NCHAR(1) NULL 
)

INSERT @t VALUES
    ( 'A' , 1 , NULL ),
    ( 'A' , 2 , '' ),
    ( 'A' , 4 , 'Y' ),
    ( 'B' , 1 , '' ),
    ( 'B' , 2 , 'N' ),  -- change from your sample data
    ( 'C' , 1 , 'Y' ),
    ( 'D' , 1 , 'N' ),
    ( 'D' , 2 , 'O' ),
    ( 'D' , 3 , 'Y' )

以下是查询本身:

SELECT transaction_id, decision_id, accepted_ind FROM ( 
SELECT transaction_id, decision_id, accepted_ind, 
    ROW_NUMBER() OVER (
        PARTITION BY transaction_id 
        ORDER BY
            CASE
                WHEN accepted_ind = 'Y' THEN 1
                WHEN decision_id = 1 THEN 2
                ELSE 3
            END
    ) rn
FROM @t
) Raw
WHERE rn = 1

结果:

transaction_id decision_id accepted_ind
-------------- ----------- ------------
A              4           Y
B              1            
C              1           Y
D              3           Y

ROW_NUMBER()子句为您提到的每个标准提供“优先级”;然后我们ORDER BY选择最好的,并取第一行。

答案 2 :(得分:0)

可能有一个更整洁/更有效的查询,但我认为这将完成工作。它假设表名是Decision:

  SELECT CASE 
         WHEN accepteddecision.transaction_id IS NOT NULL THEN 
         accepteddecision.transaction_id 
         ELSE firstdecision.transaction_id 
       END AS transaction_id, 
       CASE 
         WHEN accepteddecision.decision_id IS NOT NULL THEN 
         accepteddecision.decision_id 
         ELSE firstdecision.decision_id 
       END AS decision_id, 
       CASE 
         WHEN accepteddecision.accepted_ind IS NOT NULL THEN 
         accepteddecision.accepted_ind 
         ELSE firstdecision.accepted_ind 
       END AS accepted_ind 
FROM   decision 
       LEFT OUTER JOIN (SELECT * 
                        FROM   decision AS accepteddecision 
                        WHERE  accepteddecision.accepted_ind = 'Y') AS 
                       accepteddecision 
         ON accepteddecision.transaction_id = decision.transaction_id 
       LEFT OUTER JOIN (SELECT * 
                        FROM   decision AS firstdecision 
                        WHERE  firstdecision.decision_id = 1) AS firstdecision 
         ON firstdecision.transaction_id = decision.transaction_id 
GROUP  BY accepteddecision.transaction_id, 
          firstdecision.transaction_id, 
          accepteddecision.decision_id, 
          firstdecision.decision_id, 
          accepteddecision.accepted_ind, 
          firstdecision.accepted_ind 

答案 3 :(得分:0)

出于兴趣,以下使用问题标题中指定的UNIONEXCEPT(加上JOIN):

WITH T AS (SELECT * FROM (
              VALUES ('A', 1, NULL),
                     ('A', 2, ''),
                     ('A', 4, 'Y'),
                     ('B', 1, ''),
                     ('B', 2, 'Y'),
                     ('C', 1, 'Y'),
                     ('D', 1, 'N'),
                     ('D', 2, 'O'),
                     ('D', 3, 'Y'), 
                     ('E', 2, 'O'), -- smaple data extended
                     ('E', 1, 'N')  -- smaple data extended
             ) AS T (transaction_id, decision_id, accepted_ind)
     ) 
SELECT * 
  FROM T
 WHERE accepted_ind = 'Y'
UNION
SELECT T.* 
  FROM (
        SELECT transaction_id
          FROM T
         WHERE decision_id = 1
        EXCEPT 
        SELECT transaction_id
          FROM T
         WHERE accepted_ind = 'Y'
       ) D
       JOIN T 
          ON T.transaction_id = D.transaction_id
             AND T.decision_id = 1;
相关问题