T-SQL问题

时间:2009-06-15 05:22:36

标签: sql tsql dd

我有下表(SQL Server)表名是LandParcels

Blockid   ParcelNo  Stateorprivate
========================
11001901   30       Deemana
11001901   35       Deemana
11001901   41       State
11001901   45       State
11001901   110      Private
11001901   111      Private

11001902   1        Deemana
11001902   11       State
11001902   16       Private

11002001   15       Deemana
11002001   16       State
11003001   20       Private
11002003   2        Deemana
11002003   3        State
11003003   4        Private

Blockid(数字)=用于地籍图号码的前6位数字和用于块号码的最后2位数字

例如:110019是地籍地图no,01是Block No.

我使用了以下查询

select substring(ltrim(str(blockid)),1,6) as blockid,stateorprivate, count(*) as noofLP from LandParcels group by blockid, stateorprivate order by blockid asc

结果是

Blockid  Stateorprivate  noofLP
========================
110019   Deemana         2
110019   State           2
110019   Private         2
110019   Deemana         1
110019   State           1
110019   Private         1
110020   Deemana         1
110020   State           1
110020   Private         1
110020   Deemana         1
110020   State           1
110020   Private         1

我想获得报告的以下结果

blockid  noofBlocks   Deemana   State  Private  Amt_of_Deemana_State_Private
110019    2            3          3       3          9  
110020    2            2          2       2          6

如何查询。 Pl帮助我。

5 个答案:

答案 0 :(得分:2)

我不会检查这是否有效,但你应该看一下使用sum和case。

select
substring(ltrim(str(blockid)),1,6) as blockid,
sum(case stateorprivate when 'Deemana' then 1 else 0 end) as Deemana,
sum(case stateorprivate when 'State' then 1 else 0 end) as State,
sum(case stateorprivate when 'Private' then 1 else 0 end) as Private,
count(*) as Amt_of_Deemana_State_Private
from LandParcels group by blockid 
order by blockid asc

答案 1 :(得分:1)

您开始查询:

select substring(ltrim(str(blockid)),1,6) as blockid

会立即给DB带来歧义 - 在查询的其余部分,blockid代表该名称的原始列,还是代表这个同名的?

不要这样做 - 让数据库引擎过载比现有的处理更加模糊是荒谬的。当 是您的意思时,请使用as myblockid或此处的任何内容以及myblockid查询的其余部分。这可能无法解决所有问题,但它会让你的生活,数据库引擎,以及任何试图帮助你的人,更不用说噩梦了。

答案 2 :(得分:1)

你可以这样做:

SELECT 
    SUBSTRING(LTRIM(STR(Blockid)), 1, 6) AS blockid,
    COUNT(DISTINCT SUBSTRING(LTRIM(STR(Blockid)), 7, 2)) AS noofBlocks,
    SUM(CASE Stateorprivate WHEN 'Deemana' THEN 1 ELSE 0 END) AS Deemana,
    SUM(CASE Stateorprivate WHEN 'State' THEN 1 ELSE 0 END) AS [State],
    SUM(CASE Stateorprivate WHEN 'Private' THEN 1 ELSE 0 END) AS [Private],
    SUM(CASE Stateorprivate
        WHEN 'Deemana' THEN 1
        WHEN 'State' THEN 1
        WHEN 'Private' THEN 1
        ELSE 0
    END) AS Amt_of_Deemana_State_Private
FROM LandParcels
GROUP BY SUBSTRING(LTRIM(STR(Blockid)), 1, 6)

但是,如果数据库架构在您的控制之下,则应考虑进行规范化。

答案 3 :(得分:0)

这样的东西?

SELECT substring(ltrim(str(lp.blockid)),1,6) as blockid, 
    w.noofBlocks
    x.Deemana,
    y.State,
    z.Private,
    COUNT(*) AS Amt_of_Deemana_State_Private
FROM LandParcels lp
    INNER JOIN (
        SELECT substring(ltrim(str(lp.blockid)),1,6) as myblockid, COUNT(*) AS Deemana
        FROM LandParcels lp2
        WHERE Stateorprivate = 'Deemana'
    ) x ON (substring(ltrim(str(lp.blockid)),1,6) = x.myblockid)
    INNER JOIN (
        SELECT substring(ltrim(str(lp.blockid)),1,6) as myblockid, COUNT(*) AS State
        FROM LandParcels lp3
        WHERE Stateorprivate = 'State'
    ) y ON (substring(ltrim(str(lp.blockid)),1,6) = y.myblockid)
    INNER JOIN (
        SELECT substring(ltrim(str(lp.blockid)),1,6) as myblockid, COUNT(*) AS Private
        FROM LandParcels lp4
        WHERE Stateorprivate = 'Private'
    ) z ON (substring(ltrim(str(lp.blockid)),1,6) = z.myblockid)
    CROSS JOIN (
        SELECT COUNT(DISTINCT substring(ltrim(str(lp.blockid)),1,6) as myblockid)
        FROM LandParcels lp5
    ) w
GROUP BY substring(ltrim(str(lp.blockid)),1,6)

答案 4 :(得分:0)

我相信此查询将达到您想要的结果,但NoOfBlocks字段是第一列而不是第二列。我还使用CadastalMapNo作为结果集列名而不是结果集来自Alex Martelli的建议,它增加了歧义,因为已经存在其他名为blockid的东西。我将NoOfBlocks字段作为第一列的原因是因为我认为当使用distinct关键字时,SQLServer要求count函数成为选择列表中的第一个字段。

我实际上没有对此进行过测试,而且性能可能不佳,但我很清楚这是正确的,因为我理解这个问题。

    SELECT
        COUNT(DISTINCT SUBSTRING(LTRIM(STR(blockid)),7,8)) as NoOfBlocks,
        SUBSTRING(LTRIM(STR(blockid)),1,6) as CadastalMapNo, 
        (CASE WHEN Stateorprivate='Deemana' then 1 else 0 end) as Deemana,
        (CASE WHEN Stateorprivate='State' then 1 else 0 end) as State,
        (CASE WHEN Stateorprivate='Private' then 1 else 0 end) as Private,
        COUNT(*) as Amt_of_Deemana_State_Private 
    FROM 
        LandParcels
    GROUP BY 
        CadastalMapNo
    ORDER BY
        CadastalMapNo