我有一个看起来像下面提到的结果集,我从下面提到的查询中得到了结果:
LEAVE_DATE | RESOURCE_ID | TYPE
2016-05-17 | 1 | SELF
2016-05-27 | 1 | SELF
2016-05-30 | 0 | ORG
2016-05-30 | 1 | SELF
以下是给出上述结果集的SQL:
SELECT CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8) LEAVE_DATE, v.RESOURCE_ID, v.TYPE
FROM date_tbl t,tbl_leave v
WHERE t.n <= DATEDIFF(v.END_DATE, v.START_DATE) + 1
AND RESOURCE_ID IN (1,0)
AND DAYOFWEEK(CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8)) NOT IN (1,7)
ORDER BY LEAVE_DATE
我希望我的SQL应该返回所有唯一日期,但如果找到RESOURCE_ID 0和1的重复日期,我想选择RESOURCE_ID 0。
预期结果:
LEAVE_DATE | RESOURCE_ID | TYPE
2016-05-17 | 1 | SELF
2016-05-27 | 1 | SELF
2016-05-30 | 0 | ORG
请您提出一些建议,我应该如何实现这一结果?
答案 0 :(得分:0)
首先,您选择获取所有值,然后按resource_id对其进行排序,然后通过leave_date对结果进行分组。 group by将获得第一行重复。
SELECT * FROM
(
SELECT CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8) LEAVE_DATE, v.RESOURCE_ID, v.TYPE
FROM date_tbl t,tbl_leave v
WHERE t.n <= DATEDIFF(v.END_DATE, v.START_DATE) + 1
AND RESOURCE_ID IN (1,0)
AND DAYOFWEEK(CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8)) NOT IN (1,7)
ORDER BY v.RESOURCE_ID
)as x GROUP BY x.LEAVE_DATE
答案 1 :(得分:0)
假设您每个日期只需要一条记录,那么我能看到的唯一安全方法是添加序列号(按leave_date排序,然后是resource_id),并且只返回每个日期的第一条记录。
未通过以下方式测试: -
SELECT LEAVE_DATE,
RESOURCE_ID,
TYPE
FROM
(
SELECT LEAVE_DATE,
RESOURCE_ID,
TYPE,
if(@prev_leave_date=LEAVE_DATE, @cnt + 1, 1) AS cnt,
@prev_leave_date:=LEAVE_DATE
FROM
(
SELECT CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8) LEAVE_DATE,
v.RESOURCE_ID,
v.TYPE
FROM date_tbl t
INNER JOIN tbl_leave v
ON t.n <= DATEDIFF(v.END_DATE, v.START_DATE) + 1
WHERE RESOURCE_ID IN (1,0)
AND DAYOFWEEK(CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8)) NOT IN (1,7)
ORDER BY LEAVE_DATE, RESOURCE_ID
) sub0
CROSS JOIN
(
SELECT @prev_leave_date:="", @cnt:=0
) sub1
) sub2
WHERE cnt = 1
避免使用子查询的另一个选项是滥用GROUP_CONCAT。获取每一行,按LEAVE_DATE分组并在resource_id上使用GROUP_CONCAT并键入以获取每个LEAVE DATE的每个值的所有值。按resource_id排序,以便首先获得resource_id为0的那些。默认情况下,GROUP_CONCAT值由逗号分隔,因此使用SUBSTRING_INDEX从每个值中获取第一个值(请注意,如果resource_id或类型可以包含逗号,则需要指定不同的分隔符并将结果拆分)
未经过测试(没有表格声明或测试数据),但是这样: -
SELECT CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8) LEAVE_DATE,
SUBSTRING_INDEX(GROUP_CONCAT(v.RESOURCE_ID ORDER BY v.RESOURCE_ID), ',', 1) AS RESOURCE_ID,
SUBSTRING_INDEX(GROUP_CONCAT(v.TYPE ORDER BY v.RESOURCE_ID), ',', 1) AS TYPE
FROM date_tbl t
INNER JOIN tbl_leave v
ON t.n <= DATEDIFF(v.END_DATE, v.START_DATE) + 1
WHERE RESOURCE_ID IN (1,0)
AND DAYOFWEEK(CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8)) NOT IN (1,7)
GROUP BY LEAVE_DATE
ORDER BY LEAVE_DATE, RESOURCE_ID
答案 2 :(得分:0)
这是一个愚蠢的答案,但作为您对问题和评论的描述,这可能是一个简单的答案。
SELECT LEAVE_DATE, IF(COUNT(1) > 1, 0, RESOURCE_ID) AS RESOURCE_ID, IF(COUNT(1) > 1, 'ORG', `TYPE`) AS `TYPE`
FROM(
SELECT CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8) LEAVE_DATE, v.RESOURCE_ID, v.`TYPE`
FROM date_tbl t,tbl_leave v
WHERE t.n <= DATEDIFF(v.END_DATE, v.START_DATE) + 1
AND RESOURCE_ID IN (1,0)
AND DAYOFWEEK(CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8)) NOT IN (1,7)
ORDER BY LEAVE_DATE)
GROUP BY LEAVE_DATE
<强>编辑:强>
SELECT
CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8) LEAVE_DATE,
IF(COUNT(1) > 1, 0,v.RESOURCE_ID) AS RESOURCE_ID,
IF(COUNT(1) > 1, 'ORG', v.`TYPE`) AS `TYPE`
FROM date_tbl t,tbl_leave v
WHERE t.n <= DATEDIFF(v.END_DATE, v.START_DATE) + 1
-- AND RESOURCE_ID IN (1,0) -- This is what you want to remove!!!
AND DAYOFWEEK(CONVERT(v.START_DATE + INTERVAL t.n - 1 DAY USING utf8)) NOT IN (1,7)
ORDER BY LEAVE_DATE
GROUP BY LEAVE_DATE