将子查询重写为JOIN?

时间:2009-11-09 05:58:44

标签: sql sql-server join

更新:感谢Sifu Bill的建议我修改了SQL查询。现在它返回正确数量的不同资产(五个)。

是否可以将以下子查询重写为JOIN?

SELECT TOP 100 PERCENT Asset_ID, work_order_id, status_id,
downtime_hours, date_completed
FROM dbo.mtvw_wo_reason1
WHERE (Asset_ID IN
(SELECT TOP 5 Asset_ID from mtvw_wo_reason1
WHERE (Date_Completed BETWEEN '1-Oct-2009' AND '31-Oct-2009')
GROUP BY Asset_ID
ORDER BY SUM(Downtime_hours) DESC))

输出如下:

Asset_ID work_order_id status_id downtime_hours Date_Completed

SFM2019 2009-724    Completed   .5000   2009-09-01 17:55:09.000
SFM2019 2009-761    Completed   .5000   2009-09-15 09:03:39.000
SFM2019 2009-828    Completed   8.0000  2009-10-02 00:00:00.000
SFM2043 2009-683    Completed   .5000   2009-08-14 00:00:00.000
SFM2043 2009-734    Completed   1.0000  2009-09-05 00:54:33.000
SFM2043 2009-741    Completed   1.0000  2009-09-08 17:05:09.000
SFM2043 2009-756    Completed   .5000   2009-09-14 07:56:41.000
SFM2043 2009-792    Completed   1.0000  2009-09-22 00:00:00.000
SFM2043 2009-826    Completed   8.0000  2009-10-03 02:00:19.130
SFM2043 2009-983    Completed   1.0000  2009-10-30 00:00:00.000
SFM2045 2009-794    Completed   17.0000 2009-09-24 00:00:00.000
SFM2045 2009-808    Completed   1.0000  2009-09-26 16:01:25.850
SFM2045 2009-811    Completed   3.0000  2009-09-27 09:47:45.543
SFM2045 2009-816    Completed   24.0000 2009-09-30 15:14:35.000
SFM2045 2009-858    Completed   3.0000  2009-10-12 00:00:00.000
SFM2045 2009-861    Completed   .5000   2009-10-13 01:11:50.900
SFM2045 2009-975    Completed   1.0000  2009-10-28 00:00:00.000
SFM2045 2009-984    Completed   3.0000  2009-10-30 00:00:00.000
SFM2088 2009-777    Completed   .5000   2009-10-01 12:49:57.000
SFM2088 2009-853    Completed   .5000   2009-10-09 00:00:00.000
SFM2088 2009-855    Completed   10.0000 2009-10-09 00:00:00.000
SFM2200 2009-753    Completed   8.0000  2009-09-11 00:00:00.000
SFM2200 2009-830    Completed   8.0000  2009-10-09 00:00:00.000

实质上,查询需要:

  

返回前5名资产   最长的累计停机时间   十月份,和细分   相关的工作人员   资产

必须以不需要在内部查询中存在Date_Completed条件的方式重写查询(这是否可能?)。使用Sifu Bill的答案只产生了11行(应该有23行):

Sifu Bill的查询输出:

Asset_ID work_order_id status_id downtime_hours Date_Completed

SFM2045 2009-858    Completed   3.0000  2009-10-12 00:00:00.000
SFM2045 2009-861    Completed   .5000   2009-10-13 01:11:50.900
SFM2045 2009-975    Completed   1.0000  2009-10-28 00:00:00.000
SFM2045 2009-984    Completed   3.0000  2009-10-30 00:00:00.000
SFM2200 2009-830    Completed   8.0000  2009-10-09 00:00:00.000
SFM2043 2009-826    Completed   8.0000  2009-10-03 02:00:19.130
SFM2043 2009-983    Completed   1.0000  2009-10-30 00:00:00.000
SFM2088 2009-777    Completed   .5000   2009-10-01 12:49:57.000
SFM2088 2009-853    Completed   .5000   2009-10-09 00:00:00.000
SFM2088 2009-855    Completed   10.0000 2009-10-09 00:00:00.000
SFM2019 2009-828    Completed   8.0000  2009-10-02 00:00:00.000

感谢您的任何见解。

2 个答案:

答案 0 :(得分:3)

你可以尝试

SELECT  TOP 100 PERCENT 
        Asset_ID, 
        work_order_id, 
        status_id, 
        downtime_hours 
FROM    dbo.mtvw_wo_reason1 INNER JOIN
        (
            SELECT  TOP 5 
                    Asset_ID 
            from    mtvw_wo_reason1 
            GROUP   BY Asset_ID, Date_Completed 
            HAVING  Date_Completed BETWEEN '1-Oct-2009' and '31-Oct-2009' 
            ORDER BY    SUM(Downtime_hours) DESC
        ) sub ON dbo.mtvw_wo_reason1.Asset_ID = sub.Asset_ID

编辑评论:

SELECT  TOP 100 PERCENT         
        Asset_ID,         
        work_order_id,         
        status_id,         
        downtime_hours ,
        sub.Date_Completed --added
FROM    dbo.mtvw_wo_reason1 INNER JOIN        
        (                
            SELECT  TOP 5                                 
                    Asset_ID,
                    Date_Completed --added
            from    mtvw_wo_reason1                 
            GROUP   BY Asset_ID, Date_Completed                 
            HAVING  Date_Completed BETWEEN '1-Oct-2009' and '31-Oct-2009'                 
            ORDER BY SUM(Downtime_hours) DESC        
        ) sub ON dbo.mtvw_wo_reason1.Asset_ID = sub.Asset_ID

答案 1 :(得分:2)

很难猜到你打算这个查询要做什么。我建议当你问如何修复一个没有做你想做的查询时,你在问题中包含一个关于查询目的的明确陈述。否则,回答的人不能从错误的查询中推断出什么是正确的。

如果包含表的定义,它也很有用。显示此信息的最佳方法是用于定义表格的数据定义语言(即CREATE TABLE)。

我假设此语句描述了您想要的查询结果:

  

“10月期间每个Asset_ID的所有行,在该月内具有最多的累计停机时间。”

您可以获得10月份停机时间最多的资产,就像您在子查询中所做的那样:

SELECT TOP 5 Asset_ID 
FROM mtvw_wo_reason1
WHERE Date_Completed BETWEEN '2009-10-1' and '2009-10-31'
GROUP  BY Asset_ID
ORDER BY SUM(Downtime_hours) DESC

请注意,此查询可以独立运行。这是一个线索,如果您将其用作子查询,则它是非相关。也就是说,它不包含对外部查询中的值的引用。

您不希望像@astander所示,将Date_Completed添加到GROUP BY子句中。您希望群组仅针对每个资产,因此您可以获得每个资产的准确SUM()

但是,此表的选择列表不包括表中的其他列,Asset_ID每行GROUP BY将行缩减为一行。因此它不会提供您需要的所有信息。因此,您需要将其作为子查询运行。

SELECT m.Asset_ID, m.work_order_id, m.status_id, m.downtime_hours, m.Date_Completed
FROM dbo.mtvw_wo_reason1 m
JOIN (SELECT TOP 5 Asset_ID 
    FROM mtvw_wo_reason1
    WHERE Date_Completed BETWEEN '2009-10-1' and '2009-10-31'
    GROUP  BY Asset_ID
    ORDER BY SUM(Downtime_hours) DESC) sub
  ON (m.Asset_ID = sub.Asset_ID)
WHERE m.Date_Completed BETWEEN '2009-10-1' and '2009-10-31';

需要在子查询和外部查询中限制Date_Completed

PS:从我的阅读开始,TOP 100 PERCENT的唯一有效用途是在最后定义VIEW ORDER BY条款时。