SQL子查询/从单独的表中选择数据子集

时间:2012-06-18 13:32:14

标签: sql sql-server tsql

我正在编写一个SQL查询来提取单个磁带的打印使用情况。我的查询主体如下所示,但我无法选择一些特定数据来处理存储在单独表格中的仪表读数。

以下查询列出了已放入打印机的墨盒及其激活日期和停用日期。然后,我想使用MeterReadings表,根据DeviceID使用ActivatedDate和DeactivatedDate查看该期间的用法。到目前为止我所拥有的是

SELECT Devices.DeviceID, 
    Devices.DeviceDescription, 
    DeviceConsumables.ConsumableVariantID,
    ConsumableVariants.Type,
    ConsumableDescriptions.Description,
    MAX(ConsumableReadings.ReadingDate) as DeactivatedDate,
    MIN(ConsumableReadings.ReadingDate) AS ActivatedDate,
    ConsumableReadings.ChangedDate,
    CASE ConsumableVariants.ColourID
    WHEN 1 THEN MAX(MeterReadings.TotalMono) - MIN(MeterReadings.TotalMono)
    ELSE MAX(MeterReadings.TotalColour) - MIN(MeterReadings.TotalColour)
    END AS PrintingDiff,
    ConsumableVariants.ExpectedPageCoverage,
    ConsumableVariants.ExpectedPageYield

FROM Devices

LEFT JOIN DeviceConsumables ON Devices.DeviceID = DeviceConsumables.DeviceID
LEFT JOIN ConsumableVariants ON DeviceConsumables.ConsumableVariantID = ConsumableVariants.ConsumableVariantID
LEFT JOIN ConsumableReadings ON DeviceConsumables.ConsumableID = ConsumableReadings.ConsumableID
LEFT JOIN ConsumableDescriptions ON ConsumableVariants.DescriptionID = ConsumableDescriptions.ConsumableDescriptionID
LEFT JOIN MeterReadings ON DeviceConsumables.DeviceID = MeterReadings.DeviceID

WHERE ConsumableVariants.Type = '3' -- To only get toner cartridges
    AND Devices.DeviceID = '24'
    AND MeterReadings.ScanDateTime > MIN(ConsumableReadings.ReadingDate)
    AND MeterReadings.ScanDateTime < MAX(ConsumableReadings.ReadingDate)

GROUP BY devices.DeviceID, Devices.DeviceDescription,
    DeviceConsumables.ConsumableVariantID, ConsumableVariants.Type, ConsumableDescriptions.Description,
    ConsumableReadings.ChangedDate, ConsumableVariants.ColourID, ConsumableVariants.ExpectedPageCoverage,
    ConsumableVariants.ExpectedPageYield

ORDER BY Devices.DeviceID

这当前正在生成错误“聚合可能不会出现在WHERE子句中,除非它位于HAVING子句或选择列表中包含的子查询中,并且正在聚合的列是外部引用。”

计算字段ActivatedDate和DeactivatedDate是我需要的日期范围。我想使用case语句选择MAX(MeterReadings.TotalMono) - MIN(MeterReadings.TotalMono)用于黑色或白色或MAX(MeterReadings.TotalColour) - MIN(MeterReadings.TotalColour)用于颜色。这将有效地给我使用,因为读数只能向上。这有望为我提供MIN的起点使用和特定DeviceID的MAX终点用法。

如上所示,我正在加入DeviceID上的MeterReadings表。

我无法弄清楚如何在y和z之间获取设备x的MeterReadings(其中x是DeviceID,y是ActivatedDate,z是DeactivatedDate),因此我可以将一个计算列添加到case语句中。任何帮助表示赞赏。

- 编辑 为简洁起见,我不会在这里添加所有架构,但应该足够了。

设备 - 所有已知设备的列表

的DeviceID

DeviceDescription

许多描述设备的额外字段

DeviceConsumables - 哪些设备使用什么耗材

ConsumableID

DeviceID - 忘记设备密钥

ConsumableVariantID - Forign key to ConsumableVariant

ConsumableVariant - 所有消耗品变体列表

ConsumableVariantID

Type - 3此处表示碳粉,我感兴趣

ConsumableReadings

ReadingID - PK

ConsumableID - 忘记DeviceConsumables的密钥

ReadingDate - 上次阅读时

ChangedDate - 上次插入新墨盒

MeterReadings

ReadingID - PK与耗材读取的PK无关

的DeviceID

ScanDateTime - 已进行时间使用扫描

TotalMono - 扫描时的单声道总数

TotalColour扫描时的总色彩

3 个答案:

答案 0 :(得分:0)

首先,我会在您的输出中添加ColourID,以便您知道是否正在读取Mono或Color值。其次,我相信如果您从group by子句中删除ConsumableID,它应该可以工作。 ConsumableID行有一个日期,如果你在你的组中包含它,你将永远无法获得最大值和最小值,因此差异。

答案 1 :(得分:0)

您的问题出在您的加入声明中。

更改以下行:

LEFT JOIN ConsumableTypes ON ConsumableVariants.Type = ConsumableVariants.Type

类似于:

LEFT JOIN ConsumableTypes ON ConsumableVariants.Type = ConsumableTypes.Type

(或您加入的任何表格)。

答案 2 :(得分:0)

嗯,你必须打破你对嵌套查询的查询...下面的查询没有经过测试,所以它可能有一些语法问题,但它提供了一种方法来找出你在寻找...

SELECT Devices.DeviceID, 
    Devices.DeviceDescription, 
    DeviceConsumables.ConsumableVariantID,
    ConsumableVariants.Type,
    ConsumableDescriptions.Description,
    A.DeactivatedDate,
    A.ActivatedDate,
    A.ChangedDate,
    CASE ConsumableVariants.ColourID
    WHEN 1 THEN MAX(MeterReadings.TotalMono) - MIN(MeterReadings.TotalMono)
    ELSE MAX(MeterReadings.TotalColour) - MIN(MeterReadings.TotalColour)
    END AS PrintingDiff,
    ConsumableVariants.ExpectedPageCoverage,
    ConsumableVariants.ExpectedPageYield

FROM Devices

LEFT JOIN DeviceConsumables ON Devices.DeviceID = DeviceConsumables.DeviceID
LEFT JOIN ConsumableVariants ON DeviceConsumables.ConsumableVariantID = ConsumableVariants.ConsumableVariantID
LEFT JOIN ConsumableReadings ON DeviceConsumables.ConsumableID = ConsumableReadings.ConsumableID
LEFT JOIN ConsumableDescriptions ON ConsumableVariants.DescriptionID = ConsumableDescriptions.ConsumableDescriptionID
LEFT JOIN 
(
   SELECT D.DeviceID,
          MAX(CR.ReadingDate) as DeactivatedDate,
          MIN(CR.ReadingDate) AS ActivatedDate,
          CR.ChangedDate
     FROM Devices D
     LEFT JOIN DeviceConsumables DC ON D.DeviceID = DC.DeviceID
     LEFT JOIN ConsumableReadings CR ON DC.ConsumableID = CR.ConsumableID
    WHERE D.DeviceID = '24'
    GROUP BY D.DeviceID, 
            CR.ChangedDate
) AS A ON DeviceConsumables.DeviceID = A.DeviceID
LEFT JOIN MeterReadings ON A.DeviceID = MeterReadings.DeviceID
WHERE ConsumableVariants.Type = '3' -- To only get toner cartridges
    AND Devices.DeviceID = '24'
    AND MeterReadings.ScanDateTime > A.ActivatedDate
    AND MeterReadings.ScanDateTime < A.DeactivatedDate

GROUP BY devices.DeviceID, Devices.DeviceDescription,
    DeviceConsumables.ConsumableVariantID, ConsumableVariants.Type, ConsumableDescriptions.Description,
    ConsumableReadings.ChangedDate, ConsumableVariants.ColourID, ConsumableVariants.ExpectedPageCoverage,
    ConsumableVariants.ExpectedPageYield

ORDER BY Devices.DeviceID