2012-11-15 34 views
9

पर पंक्ति संख्या रीसेट करें अब मैंने तीन पूर्ण दिनों के लिए इसके साथ संघर्ष किया है और मैं इसके चारों ओर अपना सिर नहीं प्राप्त कर सकता हूं। यह मेरी "टी-एसक्यूएल अनुक्रमिक अवधि" की हालिया पोस्ट के समान है, लेकिन बिल्कुल वही नहीं है ... मैं कॉलम एक्स में बदलाव के आधार पर पंक्ति संख्या को रीसेट करना चाहता हूं (मेरे मामले में, कॉलम "कौन") ...टी-एसक्यूएल फ़ील्ड चेंज

SELECT  DISTINCT chr.custno, 
      CAST(LEFT(CONVERT(VARCHAR(20),chr.moddate,112),10)+ ' ' + chr.modtime AS DATETIME)as moddate, 
      chr.who  
FROM  <TABLE> chr 
WHERE  chr.custno = 581827 
      AND LEFT(chr.who, 5) = 'EMSZC' 
      AND chr.[description] NOT LIKE 'Recalled and viewed this customer' 
ORDER BY chr.custno 

परिणाम::

custno  moddate    who 
581827  2012-11-08 08:38:00.000  EMSZC14 
581827  2012-11-08 08:41:10.000  EMSZC14 
581827  2012-11-08 08:53:46.000  EMSZC14 
581827  2012-11-08 08:57:04.000  EMSZC14 
581827  2012-11-08 08:58:35.000  EMSZC14 
581827  2012-11-08 08:59:13.000  EMSZC14 
581827  2012-11-08 09:00:06.000  EMSZC14 
581827  2012-11-08 09:04:39.000  EMSZC49 Reset row number to 1 
581827  2012-11-08 09:05:04.000  EMSZC49 
581827  2012-11-08 09:06:32.000  EMSZC49 
581827  2012-11-08 09:12:03.000  EMSZC49 
581827  2012-11-08 09:12:38.000  EMSZC49 
581827  2012-11-08 09:14:18.000  EMSZC49 
581827  2012-11-08 09:17:35.000  EMSZC14 Reset row number to 1 

दूसरा कदम पंक्ति संख्या को जोड़ने के लिए है (मैं नहीं किया

यहाँ पहली क्वेरी कि कच्चे (ish) डेटा की एक छोटा सा नमूना देता है DISTINCT शब्द के उपयोग के कारण पहली क्वेरी में यह; इसलिए ...

WITH c1 AS (
     SELECT  DISTINCT chr.custno 
        CAST(LEFT(CONVERT(VARCHAR(20),chr.moddate,112),10)+ ' ' + chr.modtime AS DATETIME)as moddate, 
        chr.who 
     FROM  <TABLE> chr 
     WHERE  chr.custno = 581827 
        AND LEFT(chr.who, 5) = 'EMSZC' 
        AND chr.[description] NOT LIKE 'Recalled and viewed this customer' 
     ) 

SELECT ROW_NUMBER() OVER (PARTITION BY custno ORDER BY custno, moddate, who) AS RowID, custno, moddate, who 
FROM c1 

परिणाम:

RowID custno  moddate      who 
1  581827  2012-11-08 08:38:00.000  EMSZC14 
2  581827  2012-11-08 08:41:10.000  EMSZC14 
3  581827  2012-11-08 08:53:46.000  EMSZC14 
4  581827  2012-11-08 08:57:04.000  EMSZC14 
5  581827  2012-11-08 08:58:35.000  EMSZC14 
6  581827  2012-11-08 08:59:13.000  EMSZC14 
7  581827  2012-11-08 09:00:06.000  EMSZC14 
8  581827  2012-11-08 09:04:39.000  EMSZC49 Reset row number to 1 
9  581827  2012-11-08 09:05:04.000  EMSZC49 
10  581827  2012-11-08 09:06:32.000  EMSZC49 
11  581827  2012-11-08 09:12:03.000  EMSZC49 
12  581827  2012-11-08 09:12:38.000  EMSZC49 
13  581827  2012-11-08 09:14:18.000  EMSZC49 
14  581827  2012-11-08 09:17:35.000  EMSZC14 Reset row number to 1 

अगले कदम है, जहां मैं अटक कर रहा हूँ: लक्ष्य "जो" स्तंभ में मान के प्रत्येक परिवर्तन पर 1 के लिए RowID पुनर्स्थापित करने के लिए है। निम्न कोड एक "लगभग वहाँ" परिणाम हो जाता है (और यह ध्यान दिया जाना चाहिए कि मैं चुरा लिया/कहीं से इस कोड को उधार, लेकिन अब मैं वेबसाइट नहीं मिल सकता है):

WITH c1 AS (
     SELECT  DISTINCT chr.custno, 
        CAST(LEFT(CONVERT(VARCHAR(20),chr.moddate,112),10)+ ' ' + chr.modtime AS DATETIME)as moddate, 
        chr.who 
     FROM  <TABLE> chr 
     WHERE  chr.custno = 581827 
        AND LEFT(chr.who, 5) = 'EMSZC' 
        AND chr.[description] NOT LIKE 'Recalled and viewed this customer' 
     ) 
, c1a AS (
      SELECT ROW_NUMBER() OVER (PARTITION BY custno ORDER BY custno, moddate, who) AS RowID, custno, moddate, who 
      FROM c1 
      ) 

SELECT x.RowID - y.MinID + 1 AS Row, 
     x.custno, x.Touch, x.moddate, x.who  
FROM (
      SELECT custno, who, MIN(RowID) AS MinID 
      FROM c1a 
      GROUP BY custno, who 
     ) AS y 
     INNER JOIN c1a x ON x.custno = y.custno AND x.who = y.who 

परिणाम:

Row custno  moddate     who 
1 581827  2012-11-08 08:38:00.000  EMSZC14 
2 581827  2012-11-08 08:41:10.000  EMSZC14 
3 581827  2012-11-08 08:53:46.000  EMSZC14 
4 581827  2012-11-08 08:57:04.000  EMSZC14 
5 581827  2012-11-08 08:58:35.000  EMSZC14 
6 581827  2012-11-08 08:59:13.000  EMSZC14 
7 581827  2012-11-08 09:00:06.000  EMSZC14 
1 581827  2012-11-08 09:04:39.000  EMSZC49 Reset row number to 1 (Hooray! It worked!) 
2 581827  2012-11-08 09:05:04.000  EMSZC49 
3 581827  2012-11-08 09:06:32.000  EMSZC49 
4 581827  2012-11-08 09:12:03.000  EMSZC49 
5 581827  2012-11-08 09:12:38.000  EMSZC49 
6 581827  2012-11-08 09:14:18.000  EMSZC49 
14 581827  2012-11-08 09:17:35.000  EMSZC14 Reset row number to 1 (Crappies.) 

वांछित परिणाम:

Row custno  moddate      who 
1 581827  2012-11-08 08:38:00.000  EMSZC14 
2 581827  2012-11-08 08:41:10.000  EMSZC14 
3 581827  2012-11-08 08:53:46.000  EMSZC14 
4 581827  2012-11-08 08:57:04.000  EMSZC14 
5 581827  2012-11-08 08:58:35.000  EMSZC14 
6 581827  2012-11-08 08:59:13.000  EMSZC14 
7 581827  2012-11-08 09:00:06.000  EMSZC14 
1 581827  2012-11-08 09:04:39.000  EMSZC49 Reset row number to 1 
2 581827  2012-11-08 09:05:04.000  EMSZC49 
3 581827  2012-11-08 09:06:32.000  EMSZC49 
4 581827  2012-11-08 09:12:03.000  EMSZC49 
5 581827  2012-11-08 09:12:38.000  EMSZC49 
6 581827  2012-11-08 09:14:18.000  EMSZC49 
1 581827  2012-11-08 09:17:35.000  EMSZC14 Reset row number to 1 

किसी भी सहायता की सराहना की है। आप भी मुझ पर घूम सकते हैं, क्योंकि मुझे यकीन है कि यह हल करने के लिए काफी आसान है - मैं बस अपने तरीके से बाहर नहीं निकल सकता।

धन्यवाद।

उत्तर

1
बजाय

:

PARTITION BY custno ORDER BY custno, moddate, who) 

कोशिश:

PARTITION BY custno, who ORDER BY custno, moddate) 
+0

कोशिश की गई है कि पहले से ही ऐसा लगता है (ऐसा लगता है कि यह काम करना चाहिए, है ना?) लेकिन यह अभी भी अंतिम पंक्ति संख्या = 14. के साथ एक ही परिणाम सेट देता है। हालांकि, मेरे विचारों को फेंकते रहें। मुझे बस कुछ आसान कदम याद आ रहा है, मुझे यकीन है। – Kris

-1

एकमात्र समाधान मैं के बारे में सोच सकते हैं RBAR प्रक्रिया के माध्यम से एक कर्सर (ओह) का उपयोग करें और पीड़ित है। एक सुंदर समाधान नहीं है क्योंकि कर्सर को 1 मीटर पंक्तियों से अधिक पढ़ना होगा। ओह।

18

यदि आप SQL Server 2012 पर हैं तो आप पिछले पंक्ति के साथ मूल्य की तुलना करने के लिए LAG का उपयोग कर सकते हैं और आप परिवर्तनों को रिकॉर्ड करने के लिए SUM और OVER का उपयोग कर सकते हैं।

with C1 as 
(
    select custno, 
     moddate, 
     who, 
     lag(who) over(order by moddate) as lag_who 
    from chr 
), 
C2 as 
(
    select custno, 
     moddate, 
     who, 
     sum(case when who = lag_who then 0 else 1 end) 
      over(order by moddate rows unbounded preceding) as change 
    from C1 
) 
select row_number() over(partition by change order by moddate) as RowID, 
     custno, 
     moddate, 
     who 
from C2 

SQL Fiddle

अद्यतन:

एसक्यूएल सर्वर 2005 के लिए एक संस्करण यह एक पुनरावर्ती CTE और डेटा तुम पर पुनरावृति करने की आवश्यकता करने के बीच के भंडारण के लिए एक अस्थायी तालिका का उपयोग करता।

create table #tmp 
(
    id int primary key, 
    custno int not null, 
    moddate datetime not null, 
    who varchar(10) not null 
); 

insert into #tmp(id, custno, moddate, who) 
select row_number() over(order by moddate), 
     custno, 
     moddate, 
     who 
from chr; 

with C as 
(
    select 1 as rowid, 
     T.id, 
     T.custno, 
     T.moddate, 
     T.who, 
     cast(null as varchar(10)) as lag_who 
    from #tmp as T 
    where T.id = 1 
    union all 
    select case when T.who = C.who then C.rowid + 1 else 1 end, 
     T.id, 
     T.custno, 
     T.moddate, 
     T.who, 
     C.who 
    from #tmp as T 
    inner join C 
     on T.id = C.id + 1 
) 
select rowid, 
     custno, 
     moddate, 
     who 
from C 
option (maxrecursion 0); 

drop table #tmp; 

SQL Fiddle

+0

दुर्भाग्यवश, हम अभी भी अगले महीने 2008R2 में अपग्रेड करने की योजना के साथ 2005 चला रहे हैं। एलएजी समारोह इस समस्या का एक साफ समाधान होगा। इसे मेरे ध्यान में लाने के लिए धन्यवाद ... SQL सर्वर 2012 में जाने के लिए बस एक और तर्क। – Kris

+0

बहुत अच्छा समाधान। मेरी एकमात्र चिंता (और यह वास्तव में स्थापित नहीं है) maxrecursion के साथ 0 का उपयोग है। इससे अनंत लूप हो सकता है, लेकिन मेरी डेटा संरचना के बारे में सोचने में, शायद मुझे जो डेटा मिला है उसके साथ नहीं। धन्यवाद!!! – Kris

+0

@ क्रिस आप का स्वागत है। –

4

मैं रैंक() का उपयोग करके इस मुद्दे से सफलता मिली:

SELECT RANK() OVER (PARTITION BY who ORDER BY custno, moddate) AS RANK 

यह अपने वांछित परिणाम नहीं आए। मुझे वास्तव में यह पोस्ट एक ही समस्या को हल करने की कोशिश कर रहा है।