SQL如果满足所有匹配条件,则选择foo,返回foo

时间:2017-11-01 20:33:47

标签: sql sql-server tsql

  • 长积累问题简单答案......

我知道这需要某种子查询...

但是我正在加入3个表并试图获得输出......

  

table one 'Status' Contains many pk_tickNum id | pk_tickNum | Status | time

     

/*table two 'Order' Only One Order*/ id | pk_order_num | tickNum | taker

     

/*table three 'Transaction' Many Transactions, Many Item_num, One location p/item*/ id | pk_transaction | tickNum | item_num | Location

我有一个声明说......

Select 
ticket1.pk_tickNum,ticket1.status,ticket1.time,order.pk_order_num 
From 
Status ticket1 left join Status ticket2 
ON
(ticket1.pk_tickNum = ticket2.pk_tickNum AND ticket1.ID < ticket2.ID)
Inner Join
order
ticket1.pk_tickNum = order.tickNum
WHERE
(ticket2.ID IS NULL)

这将为我提供订单的最新状态....

完美的工作!但是,我们有Bins,即:Locations。每个订单都有多个项目...... 当物品在仓库中移动时,每个location都会被记录下来。因此,对于每个order,有多个items,每个item都有location,以包含标记结尾的'shipped' location。< / p>

如果我将上述查询运行到left join第三个Transaction表,我会在单个事务中获得与item_num一样多的条目。我不需要那个!

如果机票上的所有 status ,我所需要的只是当前items机票的单一输出location='shipped'

编辑 -

内容

状态

id | pk_tickNum | Status | 1 | 123456 | Green | 2 | 123457 | Blue | 3 | 123456 | Yellow | 4 | 123456 | Red | 5 | 123457 | Green |

顺序

id | pk_order_num | tickNum | 1 | 987654 | 123456 2 | 987656 | 123457

交易

id | pk_transaction | tickNum | item_num | Location 1 | 5555555555 | 123456 | Some | Floor 2 | 5555555556 | 123456 | Thing | Floor 3 | 5555555557 | 123456 | Smart | Shipped 4 | 5555555558 | 123456 | or | Shipped 5 | 5555555559 | 123457 | Really | Shipped 6 | 5555555560 | 123457 | Noth | Shipped 7 | 5555555561 | 123457 | ing | Shipped

输出 - pk_order_num | pk_tickNum | Status | 987654 | 123456 | Red | /*987656 | 123457 | Green |*/ This should not show!

答! - 由@Used_By_Already发布并提供示例代码available at SQLfiddle

谢谢!

2 个答案:

答案 0 :(得分:0)

我真的希望你没有名为&#34; order&#34;和&#34;交易&#34;,如果你确实它们包含在[]或&#34;&#34;为了我的理智,我用了&#34; s&#34;在这些名字的末尾。

要实现此结果(available at SQLFiddle):

| pk_order_num | tickNum | Status |
|--------------|---------|--------|
|       987654 |  123456 |    Red |

我认为&#34;最近的&#34;状态表中的行由ID列的相反顺序确定(这不是一个很好的方法,但这是唯一可用的列)。一个更好的专栏将是&#34;最后更新&#34;以此为基础的日期时间值,可能是该表中的列[时间],但没有为其提供数据。

SELECT
        o.pk_order_num
      , o.tickNum
      , s.Status
FROM [orders] o
INNER JOIN (
            select pk_tickNum, Status
                 , row_number() over(partition by pk_tickNum
                                     order by id desc) rn
            from status 
           ) s ON o.ticknum = s.pk_tickNum and s.rn = 1
INNER JOIN (
        SELECT
                ticknum
        FROM [transactions]
        GROUP BY ticknum
        HAVING COUNT(*) <> SUM(CASE WHEN Location = 'shipped' THEN 1 ELSE 0 END)
    ) t ON s.pk_tickNum = t.ticknum
;

另请注意,使用having clause的最终子查询确定是否已发送事务中的所有详细信息。该子查询只返回带有未发货交易的订单。

答案 1 :(得分:0)

Select 
  s.pk_tickNum, s.status, s.time, o.pk_order_num 
From Status s
-- actually this join already multiplies rows: ticket 123456 has more than one record in Status table in your sample data
Inner Join order o ON s.pk_tickNum = o.tickNum
WHERE NOT EXISTS
  (
    -- why is it named `pk_tickNum` if this is not a PK?
    SELECT 1 FROM Status ticket2 
    WHERE s.pk_tickNum = ticket2.pk_tickNum AND s.ID < ticket2.ID
  )
  AND NOT EXISTS
  (
    -- might catch "empty orders" if any
    SELECT 1 FROM Transaction t
    WHERE t.tickNum = s.pk_tickNum 
      and t.Location = 'shipped'
  )

请注意,您的示例数据的输出将为空,因为故障单123456有两个位置“已发货”且违反您所描述的条件的项目。