Sql 与并集和计数不同
我在数据库中有一个查询,在一个每天有可用时间的议程表中返回6个结果,例如:_08:10:00:000 | 08:30:00:000 uu和时段示例:T代表下午或M代表上午 我已经康复了,但我有一个无法解决的问题。 我只能有一天中每个时段的时间表 示例:在2015-12-19,我上午和下午各有一段时间,但在2015-12-19,我上午和下午都不能有两个小时 我的问题是:Sql 与并集和计数不同,sql,sql-server,Sql,Sql Server,我在数据库中有一个查询,在一个每天有可用时间的议程表中返回6个结果,例如:_08:10:00:000 | 08:30:00:000 uu和时段示例:T代表下午或M代表上午 我已经康复了,但我有一个无法解决的问题。 我只能有一天中每个时段的时间表 示例:在2015-12-19,我上午和下午各有一段时间,但在2015-12-19,我上午和下午都不能有两个小时 我的问题是: SELECT * FROM ( SELECT TOP(3) agendaidentificador,agendadata
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
FROM AGENDA
WHERE
agendaconsumolocktempo IS NULL
AND
agendaconsumoidentificador IS NULL
AND
agendadata > GETDATE()
GROUP BY
agendaidentificador,
agendadata
HAVING
CAST(DATEPART(HOUR,agendadata) AS INT) < 12
ORDER BY
NEWID(),
agendadata asc
) A
UNION
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo
FROM AGENDA
WHERE
agendaconsumolocktempo IS NULL
AND
agendaconsumoidentificador IS NULL
AND
agendadata > GETDATE()
GROUP BY
agendaidentificador,
agendadata
HAVING
CAST(DATEPART(HOUR,agendadata) AS INT) >= 12
AND
COUNT(CAST(agendadata AS DATE)) = 1
ORDER BY
NEWID(),
agendadata asc
) B
GROUP BY
agendaidentificador,
agendadata,
periodo
HAVING
COUNT(CAST(agendadata as DATE)) = 1
ORDER BY agendadata
不能发生相同的情况,如第1行和第2行。您必须按AgendaData的datepart按最后一个group by进行分组。不能按整个日期+时间字段分组
我认为这应该是可行的:分组到“CHARtimestamp”字段,“YYYY-MM-DD”让我们制作一些测试数据:
DECLARE @AGENDA TABLE
(
agendaIdentificador int,
agendaData datetime,
periodo varchar(1),
agendaconsumolocktempo int,
agendaconsumoidentificador int
)
INSERT INTO @AGENDA
( agendaIdentificador, agendaData, periodo, agendaconsumolocktempo, agendaconsumoidentificador )
VALUES
(173352, '2015-01-12 12:50:00.000', 'T', null, null),
(173353, '2015-01-12 12:50:00.000', 'T', null, null),
(173354, '2015-01-12 12:50:00.000', 'T', null, null),
(173355, '2015-01-12 12:50:00.000', 'T', null, null),
(173356, '2015-01-13 12:50:00.000', 'T', null, null),
(173363, '2015-01-12 14:40:00.000', 'T', null, null),
(175255, '2015-01-19 11:30:00.000', 'M', null, null),
(175520, '2015-01-26 14:50:00.000', 'T', null, null),
(125074, '2015-02-25 08:20:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-25 08:40:00.000', 'M', null, null),
(125076, '2015-02-26 08:40:00.000', 'M', null, null);
现在,我修复了测试数据,将上午和下午的所有记录分离出来,并对它们进行计数
WITH AGENDA AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE), periodo ORDER BY agendaData) RN
FROM @AGENDA
)
现在我们接受前面的查询,但是下午会话的更改是我只想要每个集合中的第一个,其中RN=1
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
FROM AGENDA
WHERE agendaconsumolocktempo IS NULL
AND agendaconsumoidentificador IS NULL
AND agendadata > GETDATE()
AND DATEPART(HOUR,agendadata) < 12
AND RN = 1
GROUP BY
agendaidentificador,
agendadata
ORDER BY
NEWID(),
agendadata asc
) A
UNION
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo
FROM AGENDA
WHERE agendaconsumolocktempo IS NULL
AND agendaconsumoidentificador IS NULL
AND agendadata > GETDATE()
and RN = 1
and DATEPART(HOUR,agendadata) >= 12
GROUP BY
agendaidentificador,
agendadata
ORDER BY
NEWID(),
agendadata asc
) B
GROUP BY
agendaidentificador,
agendadata,
periodo
ORDER BY agendadata
我添加了更多重复记录,清理了所有基于@Kevin Cook answer的无用having子句,我刚刚添加了其他CTE,这解决了我的问题
WITH CTE_AGENDA AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE) ORDER BY newid(),agendaData) RN
FROM AGENDA
)
,CTE_AGENDA2 AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE) ORDER BY newid(),agendaData desc) RN2
FROM AGENDA
)
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
FROM AGENDA
WHERE
agendaconsumolocktempo IS NULL
AND
agendaconsumoidentificador IS NULL
AND
agendadata > GETDATE()
GROUP BY
agendaidentificador,
agendadata
HAVING
CAST(DATEPART(HOUR,agendadata) AS INT) < 12
ORDER BY
NEWID(),
agendadata asc
) A
UNION
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo
FROM AGENDA2
WHERE
agendaconsumolocktempo IS NULL
AND
agendaconsumoidentificador IS NULL
AND
agendadata > GETDATE()
and RN2 = 1
GROUP BY
agendaidentificador,
agendadata
HAVING
CAST(DATEPART(HOUR,agendadata) AS INT) >= 12
ORDER BY
NEWID(),
agendadata asc
) B
GROUP BY
agendaidentificador,
agendadata,
periodo
HAVING
COUNT(CAST(agendadata as DATE)) = 1
ORDER BY agendadata,periodo
您是否在子选择中随机获得前三名?请使用UNION ALL而不是UNION,因为您确实希望返回3+3行。使用UNION ALL的服务器工作更少,因为不需要从结果中消除重复项。SpectralGhost是的,我。。。jarhl我和UNION试过但都失败了。。。再次获取副本您是否仅根据日期检查副本,而不检查时间和周期?因为您的groupby与日期和时间冲突。请将groupby中的agentdata转换为日期或在cte中取消时间。您真的不需要having子句,我没有修复其余的查询。根据你的解释,我猜你允许早上有多个记录,但只有一个下午的约会?如果一天中的每个时段只有一个,那么就在联合体的两侧使用RN=1。。。下午可以返回1个以上的约会,但不到同一天我添加了几个副本,清理了代码,修复了等式的两侧,我没有用此代码获得副本。你早上收到的旧密码是重复的吗?就这样,现在它被设置为您在上一篇评论中所说的基于您的答案,我创建了第二个代理2来获取下午的点评。。。当我按照你的方式行事时,我得到了唯一的但总是预约到12:00 pm。你使用Castagendata分区上的行数作为日期,periodo ORDER BY Agendata RN?periodo是分区的一部分吗?COUNTCASTagendadata为DATE=1为什么需要强制转换?
agendaidentificador agendadata periodo
173352 2015-01-12 12:50:00.000 T
173356 2015-01-13 12:50:00.000 T
175255 2015-01-19 11:30:00.000 M
175520 2015-01-26 14:50:00.000 T
125074 2015-02-25 08:20:00.000 M
125076 2015-02-26 08:40:00.000 M
WITH CTE_AGENDA AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE) ORDER BY newid(),agendaData) RN
FROM AGENDA
)
,CTE_AGENDA2 AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY CAST(agendaData AS DATE) ORDER BY newid(),agendaData desc) RN2
FROM AGENDA
)
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'M' AS periodo
FROM AGENDA
WHERE
agendaconsumolocktempo IS NULL
AND
agendaconsumoidentificador IS NULL
AND
agendadata > GETDATE()
GROUP BY
agendaidentificador,
agendadata
HAVING
CAST(DATEPART(HOUR,agendadata) AS INT) < 12
ORDER BY
NEWID(),
agendadata asc
) A
UNION
SELECT * FROM (
SELECT TOP(3) agendaidentificador,agendadata, 'T' AS periodo
FROM AGENDA2
WHERE
agendaconsumolocktempo IS NULL
AND
agendaconsumoidentificador IS NULL
AND
agendadata > GETDATE()
and RN2 = 1
GROUP BY
agendaidentificador,
agendadata
HAVING
CAST(DATEPART(HOUR,agendadata) AS INT) >= 12
ORDER BY
NEWID(),
agendadata asc
) B
GROUP BY
agendaidentificador,
agendadata,
periodo
HAVING
COUNT(CAST(agendadata as DATE)) = 1
ORDER BY agendadata,periodo