Проблема T-SQL
У меня есть следующая таблица (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 ответов
Вы могли бы сделать что-то вроде этого:
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)
Однако, если схема базы данных находится под вашим контролем, вы должны рассмотреть вопрос о нормализации.
Вы начинаете свой запрос:
select substring(ltrim(str(blockid)),1,6) as blockid
который сразу дает БД двусмысленность - в остальной части запроса, делает blockid
означает оригинальную колонку с таким названием, или же она означает одноименную?
не делайте этого - абсурдно перегружать движок БД с еще большей двусмысленностью, чем он уже имел дело; использование as myblockid
или что там здесь, и myblockid
в остальной части запроса, когда это то, что вы имеете в виду. Это может решить не все проблемы, но сделает вашу жизнь, движок БД и жизнь тех, кто пытается вам помочь, гораздо менее страшным кошмаром.
Я не собираюсь проверять, работает ли это, но вы должны посмотреть на использование суммы и кейса.
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
Я считаю, что этот запрос даст желаемые результаты, за исключением того, что поле 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
Что-то вроде этого?
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)