Проблема T-SQL - PullRequest
       31

Проблема T-SQL

0 голосов
/ 15 июня 2009

У меня есть следующая таблица (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

Как запросить это. Пожалуйста, помогите мне.

Ответы [ 5 ]

2 голосов
/ 15 июня 2009

Я не собираюсь проверять, работает ли это, но вы должны посмотреть на использование 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 голос
/ 15 июня 2009

Вы можете сделать что-то вроде этого:

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)

Однако, если схема базы данных находится под вашим контролем, вам следует подумать о нормализации.

1 голос
/ 15 июня 2009

Вы начинаете свой запрос:

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

, что сразу дает БД двусмысленность - в остальной части запроса blockid обозначает исходный столбец с таким именем или же это одноименный?

не делайте этого - абсурдно перегружать движок БД с еще большей двусмысленностью, чем ему приходилось иметь дело; используйте as myblockid или что-то еще здесь, и myblockid в остальной части запроса, когда , что - это то, что вы имеете в виду. Это, возможно, не решит все проблемы, но сделает вашу жизнь, движок БД и жизнь тех, кто пытается вам помочь, гораздо менее страшным кошмаром.

0 голосов
/ 15 июня 2009

Я считаю, что этот запрос даст желаемые результаты, за исключением того, что поле NoOfBlocks является первым столбцом, а не вторым столбцом. Я также использовал CadastalMapNo для имени столбца набора результатов вместо blockid по предложению Алекса Мартелли, что это добавило двусмысленность, потому что уже было что-то еще с именем blockid. Причина, по которой я поместил поле NoOfBlocks в качестве первого столбца, заключается в том, что я считаю, что 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
0 голосов
/ 15 июня 2009

Как то так?

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)
...