2008-08-22 11 views
7

एसक्यूएल विशेषज्ञ,डेटा का समूह

एसक्यूएल का उपयोग कर डेटा के साथ समूह चलाने के लिए एक प्रभावी तरीका है?
या यह कोड में डेटा को संसाधित करने के लिए और अधिक कुशल होने जा रहा है।

उदाहरण के लिए अगर मैं निम्न डेटा है: मैं इस प्रदर्शित करने के लिए की जरूरत है

ID|Name 
01|Harry Johns 
02|Adam Taylor 
03|John Smith 
04|John Smith 
05|Bill Manning 
06|John Smith 

:

Harry Johns 
Adam Taylor 
John Smith (2) 
Bill Manning 
John Smith 

@Matt: माफ करना, मैं मुसीबत एक एम्बेडेड HTML तालिका यह काम का उपयोग कर डेटा स्वरूपण था पूर्वावलोकन में लेकिन अंतिम प्रदर्शन में नहीं।

उत्तर

2

इस प्रयास करें:

select n.name, 
    (select count(*) 
    from myTable n1 
    where n1.name = n.name and n1.id >= n.id and (n1.id <= 
     (
     select isnull(min(nn.id), (select max(id) + 1 from myTable)) 
     from myTable nn 
     where nn.id > n.id and nn.name <> n.name 
     ) 
    )) 
from myTable n 
where not exists (
    select 1 
    from myTable n3 
    where n3.name = n.name and n3.id < n.id and n3.id > (
      select isnull(max(n4.id), (select min(id) - 1 from myTable)) 
      from myTable n4 
      where n4.id < n.id and n4.name <> n.name 
      ) 
) 

मुझे लगता है कि आप क्या चाहते हैं करेंगे। हालांकि एक कड़वाहट की बिट।

पुhew! कुछ संपादनों के बाद मुझे लगता है कि मेरे पास सभी एज केस हैं।

+0

जो समूह समूह एक विशेष नाम के साथ पंक्तियां करेंगे। ओपी निरंतर पंक्तियों को समूहित करना चाहता था, मुझे एसक्यूएल में ऐसा करने के तरीके से अवगत नहीं है। – Nickolay

0

इस विशेष मामले के लिए, तुम सब करने की जरूरत है नाम से समूह है और इस तरह की गिनती के लिए पूछना,:

select Name, count(*) 
from MyTable 
group by Name 

है कि आप एक दूसरे स्तंभ के रूप में प्रत्येक नाम के लिए गणना में भी।

आप इस तरह श्रृंखलाबद्ध द्वारा एक स्तंभ के रूप में यह सब प्राप्त कर सकते हैं:

select Name + ' (' + cast(count(*) as varchar) + ')' 
from MyTable 
group by Name 
1

खैर, यह:

Harry Johns, 1 
Adam Taylor, 1 
John Smith, 2 
Bill Manning, 1 

और इस (:

select Name, count(Id) 
from MyTable 
group by Name 

आप इस दे देंगे एमएस एसक्यूएल वाक्यविन्यास):

select Name + 
    case when (count(Id) > 1) 
     then ' ('+cast(count(Id) as varchar)+')' 
     else '' 
    end 
from MyTable 
group by Name 

आप दे देंगे इस:

Harry Johns 
Adam Taylor 
John Smith (2) 
Bill Manning 

आप वास्तव में चाहते हैं कि अपने परिणामों के अंत पर अन्य जॉन स्मिथ?

संपादित करें: ओह, मैं देखता हूं, आप लगातार रन बनाना चाहते हैं। उस स्थिति में, मैं कहूंगा कि आपको कर्सर की आवश्यकता है या इसे अपने प्रोग्राम कोड में करना है।

2

मुझे कर्सर से जुनून से नफरत है ... लेकिन यहां एक डोडी कर्सर संस्करण है ...

Declare @NewName Varchar(50) 
Declare @OldName Varchar(50) 
Declare @CountNum int 
Set @CountNum = 0 

DECLARE nameCursor CURSOR FOR 
SELECT Name 
FROM NameTest 
OPEN nameCursor 

FETCH NEXT FROM nameCursor INTO @NewName 

    WHILE @@FETCH_STATUS = 0 

    BEGIN 

     if @OldName <> @NewName 
     BEGIN 
     Print @OldName + ' (' + Cast(@CountNum as Varchar(50)) + ')' 
     Set @CountNum = 0 
     END 
     SELECT @OldName = @NewName 
     FETCH NEXT FROM nameCursor INTO @NewName 
     Set @CountNum = @CountNum + 1 

    END 
Print @OldName + ' (' + Cast(@CountNum as Varchar(50)) + ')' 

CLOSE nameCursor 
DEALLOCATE nameCursor 
1

कैसे इस बारे में:

declare @tmp table (Id int, Nm varchar(50)); 

insert @tmp select 1, 'Harry Johns'; 
insert @tmp select 2, 'Adam Taylor'; 
insert @tmp select 3, 'John Smith'; 
insert @tmp select 4, 'John Smith'; 
insert @tmp select 5, 'Bill Manning'; 
insert @tmp select 6, 'John Smith'; 

select * from @tmp order by Id; 

select Nm, count(1) from 
(
select Id, Nm, 
    case when exists (
     select 1 from @tmp t2 
     where t2.Nm=t1.Nm 
     and (t2.Id = t1.Id + 1 or t2.Id = t1.Id - 1)) 
     then 1 else 0 end as Run 
from @tmp t1 
) truns group by Nm, Run 

[संपादित करें] यही कारण है कि एक सा

select Nm, count(1) from (select Id, Nm, case when exists (
     select 1 from @tmp t2 where t2.Nm=t1.Nm 
     and abs(t2.Id-t1.Id)=1) then 1 else 0 end as Run 
from @tmp t1) t group by Nm, Run 
2

बस के लिए kicks मेरे समाधान (यह एक मजेदार व्यायाम था) छोटा किया जा सकता है, कोई कर्सर, कोई पुनरावृत्ति नहीं है, लेकिन मेरे पास एक सहायक क्षेत्र है

-- Setup test table 
DECLARE @names TABLE (
         id  INT     IDENTITY(1,1), 
         name NVARCHAR(25)  NOT NULL, 
         grp  UNIQUEIDENTIFIER NULL 
         ) 

INSERT @names (name) 
SELECT 'Harry Johns' UNION ALL 
SELECT 'Adam Taylor' UNION ALL 
SELECT 'John Smith'  UNION ALL 
SELECT 'John Smith'  UNION ALL 
SELECT 'Bill Manning' UNION ALL 
SELECT 'Bill Manning' UNION ALL 
SELECT 'Bill Manning' UNION ALL 
SELECT 'John Smith'  UNION ALL 
SELECT 'Bill Manning' 

-- Set the first id's group to a newid() 
UPDATE  n 
SET   grp = newid() 
FROM  @names n 
WHERE  n.id = (SELECT MIN(id) FROM @names) 

-- Set the group to a newid() if the name does not equal the previous 
UPDATE  n 
SET   grp = newid() 
FROM  @names n 
INNER JOIN @names b 
     ON (n.ID - 1) = b.ID 
     AND ISNULL(b.Name, '') <> n.Name 

-- Set groups that are null to the previous group 
-- Keep on doing this until all groups have been set 
WHILE (EXISTS(SELECT 1 FROM @names WHERE grp IS NULL)) 
BEGIN 
    UPDATE  n 
    SET   grp = b.grp 
    FROM  @names n 
    INNER JOIN @names b 
      ON (n.ID - 1) = b.ID 
      AND n.grp IS NULL 
END 

-- Final output 
SELECT  MIN(id)  AS id_start, 
      MAX(id)  AS id_end, 
      name, 
      count(1) AS consecutive 
FROM  @names 
GROUP BY grp, 
      name 
ORDER BY id_start 

/* 
Results: 

id_start id_end name   consecutive 
1   1  Harry Johns  1 
2   2  Adam Taylor  1 
3   4  John Smith  2 
5   7  Bill Manning 3 
8   8  John Smith  1 
9   9  Bill Manning 1 
*/ 
संबंधित मुद्दे