执行非常特定的SQL查询以不同格式放置数据时出现的问题
我在处理SQL表时遇到了一些问题,需要查询该表并将其重新格式化为另一个表以用于报告目的。以下是初始表格:执行非常特定的SQL查询以不同格式放置数据时出现的问题,sql,sql-server,sql-server-2005,Sql,Sql Server,Sql Server 2005,我在处理SQL表时遇到了一些问题,需要查询该表并将其重新格式化为另一个表以用于报告目的。以下是初始表格: id int, logtimestamp datetime, serialnumber varchar(255), robotid int, amountconsumed float 机器人只有1到4个。每隔15-20分钟,就会添加新行。通常,每个机器人都会报告一个序列号,但情况并非总是如此。序列号可以周期性地具有重复项。
id int,
logtimestamp datetime,
serialnumber varchar(255),
robotid int,
amountconsumed float
机器人只有1到4个。每隔15-20分钟,就会添加新行。通常,每个机器人都会报告一个序列号,但情况并非总是如此。序列号可以周期性地具有重复项。这只在测试时发生,但也可能发生
我的目标是将给定一天内每个机器人ID的消耗量相加,并将这些值放入结果表中,如下所示:
id int,
logtimestamp datetime,
robot1consumed float,
robot2consumed float,
robot3consumed float,
robot4consumed float
我很难创建一个能够准确考虑以下事实的查询:
可能存在重复的序列号
并非每个序列号都有全部4个机器人ID。如果当天不存在机器人ID,则该值应设置为0。
以下是我到目前为止提出的@startDate和@endDates:
SELECT
timestamp=dateadd(month,((Year(R1.logtimestamp)-1900)*12)+Month(R1.logtimestamp)-1,Day(R1.logtimestamp)-1),
sum(R1.robot1consumed ),
sum(R2.robot1consumed ),
sum(R3.robot1consumed ),
sum(R4.robot1consumed )
FROM
Robot_Consumption R1,
Robot_Consumption R2,
Robot_Consumption R3,
Robot_Consumption R4
WHERE
R1.robotid = '1'
AND R2.robotid = '2'
AND R3.robotid = '3'
AND R4.robotid = '4'
AND R1.logtimestamp BETWEEN @startDate AND @endDate
AND R1.serialnumber = R2.serialnumber
AND R1.serialnumber = R3.serialnumber
AND R1.serialnumber = R4.serialnumber
GROUP BY
Year(R1.logtimestamp), Month(R1.logtimestamp), Day(R1.logtimestamp)
除了上面列出的限制之外,这种方法也可以。鉴于前面列出的约束条件,是否有建议将此查询更改为有效
SELECT '0000-00-00' + INTERVAL dte DAY AS robot_date,
id,
SUM(amountconsumed)
FROM (
SELECT 1 AS id
UNION ALL
SELECT 2
UNION ALL
SELECT 3
UNION ALL
SELECT 4
) r
-- this is to select all robotids
JOIN
(
SELECT DISTINCT TO_DAYS(logtimestamp) AS dte
FROM Robot_Consumption
WHERE logtimestamp BETWEEN @startDate AND @endDate
) rd
-- this is to select all days that have any records
LEFT OUTER JOIN
RobotConsumption rc
ON rc.robotid = r.id
AND rc.logtimestamp BETWEEN '0000-00-00' + INTERVAL dte DAY AND '0000-00-00' + INTERVAL dte + 1 DAY
WHERE NOT EXISTS
(
SELECT 1
FROM Robot_Consumption rci
WHERE rci.robotid = rc.robotid
AND rci.serial_number = rc.serial_number
AND rci.id < rc.id
)
-- this is to handle duplicates
GROUP BY
dte, id
如果需要将结果排成一行,请使用:
SELECT '0000-00-00' + INTERVAL dte DAY AS robot_date,
COALESCE(
(
SELECT SUM(amountconsumed)
FROM Robot_Consumption rc
WHERE rc.robotid = 1
AND rc.logtimestamp BETWEEN '0000-00-00' + INTERVAL dte DAY AND '0000-00-00' + INTERVAL dte + 1 DAY
AND NOT EXISTS
(
SELECT 1
FROM Robot_Consumption rci
WHERE rci.robotid = rc.robotid
AND rci.serial_number = rc.serial_number
AND rci.id < rc.id
)
), 0) AS robot1consumed,
COALESCE(
(
SELECT SUM(amountconsumed)
FROM Robot_Consumption rc
WHERE rc.robotid = 2
AND rc.logtimestamp BETWEEN '0000-00-00' + INTERVAL dte DAY AND '0000-00-00' + INTERVAL dte + 1 DAY
AND NOT EXISTS
(
SELECT 1
FROM Robot_Consumption rci
WHERE rci.robotid = rc.robotid
AND rci.serial_number = rc.serial_number
AND rci.id < rc.id
)
), 0) AS robot2consumed,
COALESCE(
(
SELECT SUM(amountconsumed)
FROM Robot_Consumption rc
WHERE rc.robotid = 3
AND rc.logtimestamp BETWEEN '0000-00-00' + INTERVAL dte DAY AND '0000-00-00' + INTERVAL dte + 1 DAY
AND NOT EXISTS
(
SELECT 1
FROM Robot_Consumption rci
WHERE rci.robotid = rc.robotid
AND rci.serial_number = rc.serial_number
AND rci.id < rc.id
)
), 0) AS robot3consumed,
COALESCE(
(
SELECT SUM(amountconsumed)
FROM Robot_Consumption rc
WHERE rc.robotid = 4
AND rc.logtimestamp BETWEEN '0000-00-00' + INTERVAL dte DAY AND '0000-00-00' + INTERVAL dte + 1 DAY
AND NOT EXISTS
(
SELECT 1
FROM Robot_Consumption rci
WHERE rci.robotid = rc.robotid
AND rci.serial_number = rc.serial_number
AND rci.id < rc.id
)
), 0) AS robot4consumed,
FROM (
SELECT DISTINCT TO_DAYS(logtimestamp) AS dte
FROM Robot_Consumption
WHERE logtimestamp BETWEEN @startDate AND @endDate
) rd
谢谢你的快速回复。我忘了提到我正在使用MicrosoftSQL2005,而响应似乎是针对MySQL的。我在将您的解决方案重新格式化为MSSQL时遇到问题我相信第二个答案就是我要寻找的,但是,将其转换为在Microsoft SQL Server上工作是一个相当大的问题,我至今无法做到这一点。