简体   繁体   English

SQL获取列以匹配CASE中的多个条件

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM