2011-12-01 26 views
38

मैं एक मेज जो इस स्कीमाएसक्यूएल सर्वर समूह के आधार पर महीने

ItemID UserID Year IsPaid PaymentDate Amount 
1   1   2009 0   2009-11-01 300 
2   1   2009 0   2009-12-01 342 
3   1   2010 0   2010-01-01 243 
4   1   2010 0   2010-02-01 2543 
5   1   2010 0   2010-03-01 475 

मैं एक प्रश्न काम कर रहे हैं जो हर महीने का योग दिखाती पाने के लिए कोशिश कर रहा हूँ है की है। अब तक मैंने डेटडिफ और नेस्टेड चुनने की कोशिश की है, लेकिन न ही मुझे वह चाहिए जो मैं चाहता हूं। यह सबसे नज़दीक है जो मुझे लगता है:

DECLARE @start [datetime] = 2010/4/1; 
SELECT ItemID, IsPaid, 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 And DateDiff(m, PaymentDate, @start) = 0 AND UserID = 100) AS "Apr", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =1 AND UserID = 100) AS "May", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =2 AND UserID = 100) AS "Jun", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =3 AND UserID = 100) AS "Jul", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =4 AND UserID = 100) AS "Aug", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =5 AND UserID = 100) AS "Sep", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =6 AND UserID = 100) AS "Oct", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =7 AND UserID = 100) AS "Nov", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =8 AND UserID = 100) AS "Dec", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =9 AND UserID = 100) AS "Jan", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =10 AND UserID = 100) AS "Feb", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =11 AND UserID = 100) AS "Mar" 
FROM LIVE L INNER JOIN Payments I ON I.LiveID = L.RECORD_KEY 
WHERE UserID = 16178 

लेकिन जब मुझे मूल्य मिलना चाहिए तो मुझे बस शून्य मिलती है। क्या मैं कुछ भूल रहा हूँ?

+0

क्या आप इसके तहत उपयोगकर्ता द्वारा भुगतान किए गए भुगतान के साथ वर्ष/माह तक कॉलम दिखाने के लिए तालिका को पिट करने का प्रयास कर रहे हैं? – William

+0

आपका उपयोगकर्ता आईडी = 16178 जहां आपके उपखंड में उपयोगकर्ता आईडी = 100 से अलग खंड है, जहां खंड? जनवरी, फरवरी और मार्च के लिए आखिरी 3 सबक्विरीज भी क्रमशः 9, 10, और 11 अप्रैल से उनके महीने के मतभेद हैं? –

+0

संभावित डुप्लिकेट [एसक्यूएल का उपयोग कर दिनांक फ़ील्ड से महीने तक समूह कैसे करें] (http://stackoverflow.com/questions/14565788/how-to-group-by-month-from-date-field-using-sql) – kurast

उत्तर

84
SELECT CONVERT(NVARCHAR(10), PaymentDate, 120) [Month], SUM(Amount) [TotalAmount] 
FROM Payments 
GROUP BY CONVERT(NVARCHAR(10), PaymentDate, 120) 
ORDER BY [Month] 

आप भी आजमा सकते:

SELECT DATEPART(Year, PaymentDate) Year, DATEPART(Month, PaymentDate) Month, SUM(Amount) [TotalAmount] 
FROM Payments 
GROUP BY DATEPART(Year, PaymentDate), DATEPART(Month, PaymentDate) 
ORDER BY Year, Month 
+5

डेटपार्ट की मुझे क्या चाहिए। धन्यवाद। – Echilon

+0

बस माइस्क्ल में कॉमा का उपयोग इस समूह द्वारा वर्ष (दिनांक), महीने (दिनांक) ' – simo

+0

पठनीयता के लिए दूसरे उत्तर की ओर प्राथमिकता। –

3
DECLARE @start [datetime] = 2010/4/1; 

होना चाहिए ...

DECLARE @start [datetime] = '2010-04-01'; 

एक तुम हो 1 से 4 2010 विभाजित है, तो फिर रूपांतरण एक तारीख के लिए। 1 9 00-01-01 से 57.5 वें दिन कौन सा है।

यह जांचने के बाद कि यह सही है या नहीं, अपने प्रारंभिकरण के बाद SELECT @start आज़माएं।

3

आप इस अक्सर क्या करने की जरूरत है, तो मैं शायद एक अभिकलन स्तंभ PaymentMonth तालिका में जोड़ होगा:

ALTER TABLE dbo.Payments ADD PaymentMonth AS MONTH(PaymentDate) PERSISTED 

यह कायम और तालिका में संग्रहीत है - तो वहाँ वास्तव में कोई प्रदर्शन भूमि के ऊपर यह क्वेरी करने के लिए। यह एक 4 बाइट आईएनटी मूल्य है - इसलिए अंतरिक्ष ओवरहेड भी न्यूनतम है।

एक बार जब आप किया है कि, आप अपनी क्वेरी को आसान बनाने में कर सकता है की तर्ज पर कुछ हो:,

SELECT ItemID, IsPaid, 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 And PaymentMonth = 1 AND UserID = 100) AS 'Jan', 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 And PaymentMonth = 2 AND UserID = 100) AS 'Feb', 
.... and so on ..... 
FROM LIVE L 
INNER JOIN Payments I ON I.LiveID = L.RECORD_KEY 
WHERE UserID = 16178 
+0

क्या कोई प्रदर्शन ओवरहेड है? यहां तक ​​कि कम स्पेक बॉक्स पर, SQL सर्वर कई मिलियन 'कनवर्टर (एनवीएआरएआरएआर (7), पेमेंटडेट, 120) प्रति सेकेंड कर सकता है। मुझे यकीन नहीं है कि एक गणना कॉलम का उपयोग करने से कोई लाभ मिलेगा (जब तक कि आप इसे अनुक्रमित नहीं करते थे) – NickG

0

अब आपकी क्वेरी को स्पष्ट रूप से केवल वर्ष = 2010 के लिए भुगतान में दिख रही है हालांकि, मुझे लगता है कि आप के लिए होती क्या आपका जनवरी/फरवरी/मार्च वास्तव में 200 9 का प्रतिनिधित्व करता है। यदि ऐसा है, तो आपको उस मामले के लिए इसे थोड़ा समायोजित करने की आवश्यकता होगी। प्रत्येक कॉलम के लिए योग मानों की आवश्यकता न रखें, केवल महीनों में दिनांक अंतर की स्थिति। बाकी को WHERE खंड में रखें।

SELECT 
     SUM(case when DateDiff(m, PaymentDate, @start) = 0 
      then Amount else 0 end) AS "Apr", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 1 
      then Amount else 0 end) AS "May", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 2 
      then Amount else 0 end) AS "June", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 3 
      then Amount else 0 end) AS "July", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 4 
      then Amount else 0 end) AS "Aug", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 5 
      then Amount else 0 end) AS "Sep", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 6 
      then Amount else 0 end) AS "Oct", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 7 
      then Amount else 0 end) AS "Nov", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 8 
      then Amount else 0 end) AS "Dec", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 9 
      then Amount else 0 end) AS "Jan", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 10 
      then Amount else 0 end) AS "Feb", 
     SUM(case when DateDiff(m, PaymentDate, @start) = 11 
      then Amount else 0 end) AS "Mar" 
    FROM 
     Payments I 
     JOIN Live L 
      on I.LiveID = L.Record_Key 
    WHERE 
      Year = 2010 
     AND UserID = 100 
11

7 को NVARCHAR के आयाम को प्रतिबंधित करें, आपूर्ति केवल "YYYY-MM"

SELECT CONVERT(NVARCHAR(7),PaymentDate,120) [Month], SUM(Amount) [TotalAmount] 
FROM Payments 
GROUP BY CONVERT(NVARCHAR(7),PaymentDate,120) 
ORDER BY [Month] 
1

एक और दृष्टिकोण है कि परिणाम में कॉलम जोड़ने को शामिल नहीं करता दिखाने के लिए कन्वर्ट करने के लिए, करने के लिए है तिथि के day घटक को शून्य-आउट करें, इसलिए 2016-07-13 और 2016-07-16 दोनों 2016-07-01 होंगे - इस प्रकार उन्हें महीने के बराबर बना दिया जाएगा।

आप एक date (नहीं एक datetime) मूल्य है, तो आप इसे सीधे शून्य कर सकते हैं:

SELECT 
    DATEADD(day, 1 - DATEPART(day, [Date]), [Date]), 
    COUNT(*) 
FROM 
    [Table] 
GROUP BY 
    DATEADD(day, 1 - DATEPART(day, [Date]), [Date]) 

आप datetime मान है, तो आप CONVERT उपयोग करने के लिए समय के- भी निकालना होगा दिन भाग:

SELECT 
    DATEADD(day, 1 - DATEPART(day, [Date]), CONVERT(date, [Date])), 
    COUNT(*) 
FROM 
    [Table] 
GROUP BY 
    DATEADD(day, 1 - DATEPART(day, [Date]), CONVERT(date, [Date])) 
5

मैं इस तरह DATEADD और DATEDIFF कार्यों के संयोजन पसंद करते हैं:

GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Created),0) 

साथ में, इन दो कार्यों शून्य-आउट तिथि घटक छोटे निर्दिष्ट DatePart से (अर्थात इस उदाहरण में MONTH)।

आप datepart बिट से YEAR, WEEK, DAY, आदि को बदल सकते हैं ... जो कि बहुत आसान है।

आपकी मूल SQL क्वेरी तब कुछ ऐसा दिखाई देगी (मैं इसका परीक्षण नहीं कर सकता क्योंकि मेरे पास डेटा सेट नहीं है, लेकिन इसे आपको सही रास्ते पर रखना चाहिए)।

DECLARE @start [datetime] = '2010-04-01'; 

SELECT 
    ItemID, 
    UserID, 
    DATEADD(MONTH, DATEDIFF(MONTH, 0, Created),0) [Month], 
    IsPaid, 
    SUM(Amount) 
FROM LIVE L 
INNER JOIN Payments I ON I.LiveID = L.RECORD_KEY 
WHERE UserID = 16178 
AND PaymentDate > @start 

एक और बात: Month स्तंभ एक DateTime जो भी एक अच्छा लाभ है अगर आप इस प्रक्रिया है कि डेटा को आगे या नक्शा यह उदाहरण के लिए आपत्ति .NET की जरूरत के रूप में लिखा गया हो।

संबंधित मुद्दे