[英]SQL getting a column to match multiple conditions in CASE
Presented with the following snippet of SQL: 带有以下SQL代码段:
CASE
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 30) THEN '>= 30 (inclusive)'
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 20) THEN '>= 20 (inclusive)'
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 10) THEN '>= 10 (inclusive)'
ELSE '< 10'
END
(The full query is below, the snippet above is just to highlight the problem) (下面是完整的查询,上面的代码段只是用来突出问题)
The above current results in exclusive matches: 以上当前结果导致互斥匹配:
(30 <= date_diff) = '>= 30'
(20 <= date_diff <= 30) = '>= 20'
(10 <= date_diff <= 20) = '>= 10'
(date_diff < 10) = '< 10'
But what I need is inclusive matches: 但是我需要的是包容性匹配:
(30 <= date_diff <= 0) = '>= 30'
(20 <= date_diff <= 0) = '>= 20'
(10 <= date_diff <= 0) = '>= 10'
(date_diff < 10) = '< 10'
So - if a record is older than 30 years, it must be categorized in in >= 10
, >= 20
as well as >= 30
, and so on. 因此-如果记录的历史超过30年,则必须将其分类为
>= 10
, >= 20
以及>= 30
,依此类推。
FULL QUERY 完整查询
SELECT
COUNT(*) AS `RecordCount`, `ExistingPlanned`, `ResponsibleOrg`, `StartDateTCDR`, `EndDateTCDR`, `SpecificEndDate`, `ResponsibleOrgOut`,
(CASE
WHEN (`EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 0) THEN '2018-12-31'
WHEN (`EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 1) THEN '-'
ELSE `EndDateTCDR`
END) AS `EndDate`,
(CASE
WHEN (`StartDateTCDR` < '1001-01-01') THEN '-'
ELSE `StartDateTCDR`
END) AS `StartDate`,
(CASE
WHEN (`StartDateTCDR` < '1001-01-01') THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 1) THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 0) THEN (
CASE
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 30) THEN '>= 30 (inclusive)'
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 20) THEN '>= 20 (inclusive)'
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 10) THEN '>= 10 (inclusive)'
ELSE '< 10'
END
)
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` > '1001-01-01') THEN (
CASE
WHEN (YEAR(`EndDateTCDR`) - YEAR(`StartDateTCDR`) - (DATE_FORMAT(`EndDateTCDR`, '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 30) THEN '>= 30 (inclusive)'
WHEN (YEAR(`EndDateTCDR`) - YEAR(`StartDateTCDR`) - (DATE_FORMAT(`EndDateTCDR`, '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 20) THEN '>= 20 (inclusive)'
WHEN (YEAR(`EndDateTCDR`) - YEAR(`StartDateTCDR`) - (DATE_FORMAT(`EndDateTCDR`, '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 10) THEN '>= 10 (inclusive)'
ELSE '< 10'
END
)
END) AS `TCDRLength`,
(CASE
WHEN (`StartDateTCDR` < '1001-01-01') THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 1) THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 0) THEN (
ROUND((DATEDIFF('2018-12-31', `StartDateTCDR`) / 365), 2)
)
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` > '1001-01-01') THEN (
ROUND((DATEDIFF(`EndDateTCDR`, `StartDateTCDR`) / 365), 2)
)
END) AS `ActualLength`
FROM `data_records`
LEFT JOIN `RespOrgLUT`
ON `ResponsibleOrgIn` = `ResponsibleOrg`
GROUP BY `ExistingPlanned`, `ResponsibleOrg`, `StartDateTCDR`, `EndDateTCDR`, `SpecificEndDate`, `ResponsibleOrgOut`, `StartDate`, `EndDate`, `ActualLength`, `TCDRLength`
ORDER BY `ResponsibleOrg` ASC, `RecordCount` DESC, `ResponsibleOrgOut` ASC, `ActualLength` DESC, `TCDRLength` DESC
LIMIT 0, 2000
EDIT 1 编辑1
Using the suggestion by @Barmar, my query now looks like this, resulting in an error: #1248 - Every derived table must have its own alias
, so I clearly implemented it wrong, so any further assistance will be appreciated. 使用@Barmar的建议,我的查询现在看起来像这样,导致错误:
#1248 - Every derived table must have its own alias
1248- #1248 - Every derived table must have its own alias
,因此我显然实现了错误,因此,我们将不胜感激。
SELECT
COUNT(*) AS `RecordCount`, `ExistingPlanned`, `ResponsibleOrg`, `StartDateTCDR`, `EndDateTCDR`, `SpecificEndDate`, `ResponsibleOrgOut`,
(CASE
WHEN (`EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 0) THEN '2018-12-31'
WHEN (`EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 1) THEN '-'
ELSE `EndDateTCDR`
END) AS `EndDate`,
(CASE
WHEN (`StartDateTCDR` < '1001-01-01') THEN '-'
ELSE `StartDateTCDR`
END) AS `StartDate`,
(CASE
WHEN (`StartDateTCDR` < '1001-01-01') THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 1) THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 0) THEN (
CASE
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 30) THEN '>= 30 (inclusive)'
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 20) THEN '>= 20 (inclusive)'
WHEN (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 10) THEN '>= 10 (inclusive)'
ELSE '< 10'
END
)
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` > '1001-01-01') THEN (
CASE
WHEN (YEAR(`EndDateTCDR`) - YEAR(`StartDateTCDR`) - (DATE_FORMAT(`EndDateTCDR`, '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 30) THEN '>= 30 (inclusive)'
WHEN (YEAR(`EndDateTCDR`) - YEAR(`StartDateTCDR`) - (DATE_FORMAT(`EndDateTCDR`, '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 20) THEN '>= 20 (inclusive)'
WHEN (YEAR(`EndDateTCDR`) - YEAR(`StartDateTCDR`) - (DATE_FORMAT(`EndDateTCDR`, '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 10) THEN '>= 10 (inclusive)'
ELSE '< 10'
END
)
END) AS `TCDRLength`,
(CASE
WHEN (`StartDateTCDR` < '1001-01-01') THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 1) THEN '-'
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` < '1001-01-01' AND `SpecificEndDate` = 0) THEN (
ROUND((DATEDIFF('2018-12-31', `StartDateTCDR`) / 365), 2)
)
WHEN (`StartDateTCDR` > '1001-01-01' AND `EndDateTCDR` > '1001-01-01') THEN (
ROUND((DATEDIFF(`EndDateTCDR`, `StartDateTCDR`) / 365), 2)
)
END) AS `ActualLength`
FROM `data_records`
LEFT JOIN `RespOrgLUT` ON `ResponsibleOrgIn` = `ResponsibleOrg`
LEFT JOIN (
SELECT `category`, COUNT(*)
FROM `data_records` dr
JOIN (
SELECT '< 10' AS `category`
UNION
SELECT '>= 10'
UNION
SELECT '>= 20'
UNION
SELECT '>= 30'
) AS c
ON (`category` = '>= 30' AND (YEAR('2018-12-31') - YEAR(`dr`.`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`dr`.`StartDateTCDR`, '%m%d')) >= 30))
OR (`category` = '>= 20' AND (YEAR('2018-12-31') - YEAR(`dr`.`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`dr`.`StartDateTCDR`, '%m%d')) >= 20))
OR (`category` = '>= 10' AND (YEAR('2018-12-31') - YEAR(`dr`.`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`dr`.`StartDateTCDR`, '%m%d')) >= 10))
OR (`category` = '< 10' AND (YEAR('2018-12-31') - YEAR(`dr`.`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`dr`.`StartDateTCDR`, '%m%d')) < 10))
)
GROUP BY `ExistingPlanned`, `ResponsibleOrg`, `StartDateTCDR`, `EndDateTCDR`, `SpecificEndDate`, `ResponsibleOrgOut`, `StartDate`, `EndDate`, `ActualLength`, `TCDRLength`
ORDER BY `ResponsibleOrg` ASC, `RecordCount` DESC, `ResponsibleOrgOut` ASC, `ActualLength` DESC, `TCDRLength` DESC
LIMIT 0, 2000
Join your table with a subquery that returns all the categories, then check whether the row fits the category. 用返回所有类别的子查询将表连接起来,然后检查该行是否适合该类别。 Here's a simplification showing just that part of the query, I don't have time right now to fill in your entire query.
这是一个简化的查询,仅显示了查询的那一部分,我现在没有时间填写您的整个查询。
SELECT category, COUNT(*)
FROM ...
JOIN (
SELECT '< 10' AS category
UNION
SELECT '>= 10'
UNION
SELECT '>= 20'
UNION
SELECT '>= 30'
) AS c ON (category = '>= 30' AND (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 30))
OR (category = '>= 20' AND (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 20))
OR (category = '>= 10' AND (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) >= 10))
OR (category = '< 10' AND (YEAR('2018-12-31') - YEAR(`StartDateTCDR`) - (DATE_FORMAT('2018-12-31', '%m%d') < DATE_FORMAT(`StartDateTCDR`, '%m%d')) < 10))
GROUP BY Category, `ExistingPlanned`, `ResponsibleOrg`, `StartDateTCDR`, `EndDateTCDR`, `SpecificEndDate`, `ResponsibleOrgOut`, `StartDate`, `EndDate`, `ActualLength`, `TCDRLength`
Another way to do it would be a UNION
of 4 queries, which each test for the age in their WHERE
clauses. 另一种方法是使用4个查询的
UNION
,每个查询都会在其WHERE
子句中测试年龄。
In this case, the solution was not necessary to be done with a single query where the processing was done on SQL side. 在这种情况下,无需在SQL端完成处理的单个查询中完成解决方案。 I opted for a broader query that got all the data at one shot, then processed the result set with PHP to get to the results I need.
我选择了一个更广泛的查询,一次获得了所有数据,然后使用PHP处理了结果集,以获得所需的结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.