自定义SQL按语句排序

时间:2014-06-11 11:54:26

标签: sql tsql sql-order-by

我想在我的sql查询中创建自定义顺序,只需更改一行位置。

这是我目前的sql结果 -

Age Category    Female  Male
-------------------------------

30-39           2772    3193
40-49           1587    2246
50-65           990     3718
Over 65         176     3487
Under 30        1359    1500

我希望他们这样排序,并且在30岁以下。在顶部 -

Age Category    Female  Male
-------------------------------

Under 30        1359    1500    
30-39           2772    3193
40-49           1587    2246
50-65           990     3718
Over 65         176     3487

这是我的代码 -

SELECT DISTINCT


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN 'Under 30'
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN '30-39'
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN '40-49' 
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN '50-65'
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN 'Over 65'
END as 'Age Category',


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) <= 30 and gender ='f' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 30 AND 39 and gender ='f' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 40 AND 49 and gender ='f' and status ='a' and member_type ='mm') 
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 50 AND 64 and gender ='f' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) >= 65 and gender ='f' and status ='a' and member_type ='mm')
END as 'Female',


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) <= 30 and gender ='m' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 30 AND 39 and gender ='m' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 40 AND 49 and gender ='m' and status ='a' and member_type ='mm') 
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 50 AND 64 and gender ='m' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) >= 65 and gender ='m' and status ='a' and member_type ='mm')
END as 'Male'


FROM NAME N1
WHERE [STATUS] ='A' AND 
  MEMBER_TYPE IN ('MM') AND
  (
   CASE 
        WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN 'Under 30'
        WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN '30-39'
        WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN '40-49' 
        WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN '50-65'
        WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN 'Over 65'
   END
  ) IS NOT NULL

group by datediff(YYYY,birth_date,getdate()), member_type

非常感谢

3 个答案:

答案 0 :(得分:2)

添加手动计算的SortOrder列,然后按此顺序和[年龄类别]

进行排序
SELECT DISTINCT


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN 'Under 30'
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN '30-39'
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN '40-49' 
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN '50-65'
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN 'Over 65'
END as 'Age Category',


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) <= 30 and gender ='f' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 30 AND 39 and gender ='f' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 40 AND 49 and gender ='f' and status ='a' and member_type ='mm') 
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 50 AND 64 and gender ='f' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) >= 65 and gender ='f' and status ='a' and member_type ='mm')
END as 'Female',


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) <= 30 and gender ='m' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 30 AND 39 and gender ='m' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 40 AND 49 and gender ='m' and status ='a' and member_type ='mm') 
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate())BETWEEN 50 AND 64 and gender ='m' and status ='a' and member_type ='mm')
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) >= 65 and gender ='m' and status ='a' and member_type ='mm')
END as 'Male'

-- Newly inserted code starts


CASE 
    WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN 1
    WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 65 THEN 3
    WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN 2
END as 'SortOrder',


-- Newly Inserted Code Ends

FROM NAME N1
WHERE [STATUS] ='A' AND 
  MEMBER_TYPE IN ('MM') AND
  (
   CASE 
        WHEN datediff(YYYY,birth_date,getdate()) <= 30 THEN 'Under 30'
        WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 30 AND 39 THEN '30-39'
        WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 40 AND 49 THEN '40-49' 
        WHEN datediff(YYYY,birth_date,getdate()) BETWEEN 50 AND 65 THEN '50-65'
        WHEN datediff(YYYY,birth_date,getdate()) >= 65 THEN 'Over 65'
   END
  ) IS NOT NULL

group by datediff(YYYY,birth_date,getdate()), member_type
-- newly inserted code
ORDER BY SortOrder, [Age Category]

答案 1 :(得分:2)

仅仅通过?添加订单就足够了     按日期订购(YYYY,birth_date,getdate())

否则,也许您也可以将年龄类别更改为&#34; 30和&#34;和&#34; 65及以上&#34;

编辑此查询可能更容易/更少重复。顺便说一句,BETWEEN子句是包容性的,所以你应该使用&lt; 30而不是&lt; = 30(并且&gt; 65而不是&gt; = 65)以确保这些年龄不被计算两次。

SELECT 'Under 30' AS 'Age Category',
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) < 30 and gender ='f' and status ='a' and member_type ='mm') AS 'Female',
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) < 30 and gender ='m' and status ='a' and member_type ='mm') AS 'Male'
UNION ALL
SELECT '30-39',
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) BETWEEN 30 AND 39 and gender ='f' and status ='a' and member_type ='mm')
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) BETWEEN 30 AND 39 and gender ='m' and status ='a' and member_type ='mm')
UNION ALL
SELECT '40-49',
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) BETWEEN 40 AND 49 and gender ='f' and status ='a' and member_type ='mm')
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) BETWEEN 40 AND 49 and gender ='m' and status ='a' and member_type ='mm')
UNION ALL
SELECT '50-65',
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) BETWEEN 50 AND 65 and gender ='f' and status ='a' and member_type ='mm')
    (select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) BETWEEN 50 AND 65 and gender ='m' and status ='a' and member_type ='mm')
UNION ALL
SELECT 'Over 65',
(select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) > 65 and gender ='f' and status ='a' and member_type ='mm')
(select count(*) from name n1 where datediff(YYYY,n1.birth_date,getdate()) > 65 and gender ='m' and status ='a' and member_type ='mm')

答案 2 :(得分:1)

如果您创建一个要加入的表,这将变得更加容易。

CREATE TABLE dim_age_band (
  id            INT,
  title         VARCHAR(32),
  ordinal       INT,
  bound_lower   INT,
  bound_upper   INT
)

INSERT INTO dim_age_band SELECT 1, 'Under 30', 1,  0,   30;
INSERT INTO dim_age_band SELECT 2, '30-39',    2, 30,   40;
INSERT INTO dim_age_band SELECT 3, '40-49',    3, 40,   50;
INSERT INTO dim_age_band SELECT 4, '50-65',    4, 50,   66;
INSERT INTO dim_age_band SELECT 5, 'Over 65',  5, 66, 1000;

SELECT
  MAX([dim_age_band].[name]                            )   AS age_band_name,
  SUM(CASE WHEN [name].[gender] = 'f' THEN 1 ELSE 0 END)   AS female,
  SUM(CASE WHEN [name].[gender] = 'm' THEN 1 ELSE 0 END)   AS male
FROM
  dim_age_band
LEFT JOIN
  name
    ON  [name].[birth_date] <= DATEADD(YYYY, GetDate(), [dim_age_band].[bound_lower])
    AND [name].[birth_date] >  DATEADD(YYYY, GetDate(), [dim_age_band].[bound_Upper])
    AND [name].[STATUS]      = 'A'
    AND [name].MEMBER_TYPE  IN ('MM')
GROUP BY
  [dim_age_band].[id]
ORDER BY
  MAX([dim_age_band].[ordinal])
;

编辑:

请注意,我在[birth_date]字段上使用DATEDIFF()也 。相反,我在今天的日期和年龄段边界上运行该计算。这意味着可以使用索引通过[name]搜索[birth_date]表;如果存在这样的指数。

编辑:

CTE版本......

WITH
  dim_age_band (name, ordinal, bound_lower, bound_upper)
AS
(
            SELECT 'Under 30', 1,  0,   30
  UNION ALL SELECT '30-39',    2, 30,   40
  UNION ALL SELECT '40-49',    3, 40,   50
  UNION ALL SELECT '50-65',    4, 50,   66
  UNION ALL SELECT 'Over 65',  5, 66, 1000
)
SELECT
  MAX([dim_age_band].[name]                            )   AS age_band_name,
  SUM(CASE WHEN [name].[gender] = 'f' THEN 1 ELSE 0 END)   AS female,
  SUM(CASE WHEN [name].[gender] = 'm' THEN 1 ELSE 0 END)   AS male
FROM
  dim_age_band
LEFT JOIN
  name
    ON  [name].[birth_date] <= DATEADD(YYYY, GetDate(), [dim_age_band].[bound_lower])
    AND [name].[birth_date] >  DATEADD(YYYY, GetDate(), [dim_age_band].[bound_Upper])
    AND [name].[STATUS]      = 'A'
    AND [name].MEMBER_TYPE  IN ('MM')
GROUP BY
  [dim_age_band].[id]
ORDER BY
  MAX([dim_age_band].[ordinal])
;

内联视图版本:

SELECT
  MAX([dim_age_band].[name]                            )   AS age_band_name,
  SUM(CASE WHEN [name].[gender] = 'f' THEN 1 ELSE 0 END)   AS female,
  SUM(CASE WHEN [name].[gender] = 'm' THEN 1 ELSE 0 END)   AS male
FROM
(
            SELECT 'Under 30' AS name, 1 AS ordinal,  0 AS bound_lower,   30 AS bound_upper
  UNION ALL SELECT '30-39'    AS name, 2 AS ordinal, 30 AS bound_lower,   40 AS bound_upper
  UNION ALL SELECT '40-49'    AS name, 3 AS ordinal, 40 AS bound_lower,   50 AS bound_upper
  UNION ALL SELECT '50-65'    AS name, 4 AS ordinal, 50 AS bound_lower,   66 AS bound_upper
  UNION ALL SELECT 'Over 65'  AS name, 5 AS ordinal, 66 AS bound_lower, 1000 AS bound_upper
)
  AS dim_age_band
LEFT JOIN
  name
    ON  [name].[birth_date] <= DATEADD(YYYY, GetDate(), [dim_age_band].[bound_lower])
    AND [name].[birth_date] >  DATEADD(YYYY, GetDate(), [dim_age_band].[bound_Upper])
    AND [name].[STATUS]      = 'A'
    AND [name].MEMBER_TYPE  IN ('MM')
GROUP BY
  [dim_age_band].[id]
ORDER BY
  MAX([dim_age_band].[ordinal])
;