0

我有下表(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 是地籍图编号,01 是区块编号。

我使用了以下查询

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

这个怎么查询。请帮帮我。

4

5 回答 5

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
于 2009-06-15T05:45:00.937 回答
1

您开始查询:

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

这立即给数据库带来了歧义——在查询的其余部分中,它blockid代表该名称的原始列,还是代表这个同名列?

不要那样做——用比它​​已经处理的更模糊的数据库引擎过载是荒谬的;在此处使用as myblockid或其他任何内容,以及myblockid在查询的其余部分中,就是您的意思。这可能无法解决所有问题,但它会让你的生活、数据库引擎以及任何试图帮助你的人的生活,更不用说是一场噩梦。

于 2009-06-15T05:33:38.530 回答
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)

但是,如果数据库模式在您的控制之下,您应该考虑规范化。

于 2009-06-15T05:51:21.263 回答
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)
于 2009-06-15T05:56:29.737 回答
0

我相信这个查询会达到你想要的结果,除了 NoOfBlocks 字段是第一列而不是第二列。根据 Alex Martelli 的建议,我还使用 CadastalMapNo 作为结果集列名称,而不是 blockid,因为它增加了歧义,因为已经有其他东西名为 blockid。我之所以将 NoOfBlocks 字段作为第一列,是因为我认为 SQLServer 在使用 distinct 关键字时要求将 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
于 2009-06-15T06:00:14.550 回答