2009-06-15 13 views
0

Ich habe folgende Tabelle (SQL Server) Tabellenname ist LandParcelsT-SQL Problem

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 (Numerisch) = die ersten 6 Ziffern verwendet für Katasters Nein und letzten 2 Ziffern für den Block Keine

zB: 110019 ist Cadastal keine Karte und 01 ist Block Nr

habe ich die folgende Abfrage

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

Ergebnis ist

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 

ich folgendes Ergebnis für einen Bericht

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

Wie abzufragen diese erhalten möchten. Pl hilf mir.

+0

Können Sie die Abfrage posten, die Sie versucht haben, um das gewünschte Ergebnis zu erhalten? – Kirtan

Antwort

1

Man könnte so etwas tun:

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) 

Wenn jedoch das Datenbankschema unter Ihrer Kontrolle ist, sollten Sie Normalisierung betrachten.

+0

Vielen Dank Jacob. Das ist die wahre Lösung für mich. Vielen Dank noch einmal. –

1

Sie starten Ihre Anfrage:

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

die unmittelbar auf die DB eine Mehrdeutigkeit gibt - in den Rest der Abfrage, nicht blockid für die ursprüngliche Spalte dieses Namens stehen, oder es für dieses gleichnamigen hat stehen ein?

tun Sie das nicht - es ist absurd, einen DB-Motor mit noch mehr Zweideutigkeit zu überlasten, als es bereits hatte; Verwenden Sie as myblockid oder was auch immer hier, und myblockid im Rest der Abfrage, wenn das ist, was Sie meinen. Dies kann nicht jedes Problem lösen, aber es wird Ihr Leben, die DB-Maschine, UND das von jedem, der versucht, Ihnen zu helfen, noch weniger ein Albtraum machen.

+0

War ich nicht, und ich schätze keine unnötigen Down-Stimmen für perfekt korrekte (wenn auch unvollständige) Antworten, besonders, weil ich mich anstrengen muss, um heute Nacht 10K zu knacken ;-) –

+0

Lies einfach die Frage noch einmal was geändert wurde, seit ich es beantwortet habe, so scheint es, dass meine Antwort nicht korrekt war, ab zu bearbeiten. (auch 10k ist es) – Tetraneutron

+0

Der SQL-Standard legt Regeln fest, wie solche möglichen Unklarheiten gehandhabt werden sollen; einige DBMS weichen von den Standardregeln ab. –

2

Ich werde nicht überprüfen, ob dies funktioniert, aber Sie sollten sich mit der Summe und Fall betrachten.

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 
0

So etwas ähnliches?

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

Ich glaube, dass diese Abfrage die gewünschten Ergebnisse erzielen wird, außer dass das NoOfBlocks-Feld die erste Spalte anstelle der zweiten Spalte ist. Ich habe auch CadastalMapNo für den Namen der Resultset-Spalte anstelle von blockid auf dem Vorschlag von Alex Martelli verwendet, dass es Mehrdeutigkeit hinzugefügt hat, weil es bereits etwas anderes namens blockid gab. Der Grund, warum ich das NoOfBlocks-Feld als erste Spalte angegeben habe, ist, weil ich glaube, dass SQL Server erfordert, dass die Zählfunktion das erste Feld in der Auswahlliste ist, wenn das distinct-Schlüsselwort verwendet wird.

Ich habe dies nicht wirklich getestet und es könnte schlechte Leistung haben, aber ich bin mir ziemlich sicher, dass es korrekt ist, wie ich die Frage verstehe.

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