2013-03-25 27 views
26

मैं एक संग्रहीत प्रक्रिया लिखने की कोशिश कर रहा हूं जो ऑर्डर ऑर्डर और सॉर्ट पैरामीटर के साथ ऑब्जेक्ट की एक सूची देता है और एसक्यूएल पैरामीटर के रूप में पास किया जाता है।टी-एसक्यूएल सशर्त आदेश

चलें कहते हैं कि मैं एक उत्पादों के निम्नलिखित कॉलम के साथ तालिका है: (पूर्णांक), नाम (varchar), मूल्य (पूर्णांक), CREATED_DATE (दिनांक) और और @sortOrder

product_id मापदंडों @sortDir मैं चाहता हूँ

select * 
from Product 
    if (@sortOrder = 'name' and @sortDir = 'asc') 
    then order by name asc 
    if (@sortOrder = 'created_date' and @sortDir = 'asc') 
    then order by created_date asc 
    if (@sortOrder = 'name' and @sortDir = 'desc') 
    then order by name desc 
    if (@sortOrder = 'created_date' and @sortDir = 'desc') 
    then order by created_date desc 

मैंने केस स्टेटमेंट के साथ ऐसा करने की कोशिश की लेकिन डेटा प्रकार अलग होने के कारण समस्याएं थीं। किसी को कोई सुझाव मिला है?

+0

आप केस स्टेटमेंट के साथ सही रास्ते पर थे। क्या आप जो पोस्ट कर सकते हैं उसे पोस्ट कर सकते हैं और हमें बता सकते हैं कि त्रुटि क्या थी? –

+0

मुझे निम्न त्रुटि मिलती है "दिनांक और/या चरित्र स्ट्रिंग से समय परिवर्तित करते समय रूपांतरण विफल रहा।" क्योंकि यदि आप केस स्टेटमेंट का उपयोग कर रहे हैं तो स्पष्ट रूप से आपके डेटा प्रकार समान होना चाहिए। – RiceRiceBaby

+0

क्या आप अपना कोड पोस्ट कर सकते हैं? –

उत्तर

47

CASE एक अभिव्यक्ति है जो एक मूल्य देता है। यह नियंत्रण के प्रवाह के लिए नहीं है, जैसे IF। और आप एक प्रश्न के भीतर IF का उपयोग नहीं कर सकते।

दुर्भाग्यवश, CASE अभिव्यक्तियों के साथ कुछ सीमाएं हैं जो इसे आप जो चाहते हैं उसे करने के लिए बोझिल बनाती हैं। उदाहरण के लिए, CASE अभिव्यक्ति की सभी शाखाओं को एक ही प्रकार को वापस करना होगा, या एक ही प्रकार में पूर्ण रूप से परिवर्तनीय होना चाहिए। मैं तारों और तिथियों के साथ कोशिश नहीं करता। क्रमबद्ध दिशा निर्दिष्ट करने के लिए आप CASE का भी उपयोग नहीं कर सकते हैं।

SELECT column_list_please 
FROM dbo.Product -- dbo prefix please 
ORDER BY 
    CASE WHEN @sortDir = 'asc' AND @sortOrder = 'name' THEN name END, 
    CASE WHEN @sortDir = 'asc' AND @sortOrder = 'created_date' THEN created_date END, 
    CASE WHEN @sortDir = 'desc' AND @sortOrder = 'name' THEN name END DESC, 
    CASE WHEN @sortDir = 'desc' AND @sortOrder = 'created_date' THEN created_date END DESC; 

एक तर्कसंगत आसान समाधान (विशेष रूप से यदि यह अधिक जटिल हो जाता है) गतिशील एसक्यूएल का उपयोग करना है। ,

IF @sortDir NOT IN ('asc', 'desc') 
    OR @sortOrder NOT IN ('name', 'created_date') 
BEGIN 
    RAISERROR('Invalid params', 11, 1); 
    RETURN; 
END 

DECLARE @sql NVARCHAR(MAX) = N'SELECT column_list_please 
    FROM dbo.Product ORDER BY ' + @sortOrder + ' ' + @sortDir; 

EXEC sp_executesql @sql; 

गतिशील एसक्यूएल के लिए एक और प्लस सब डर-mongering कि इसके बारे में फैला हुआ है के बावजूद: एसक्यूएल इंजेक्शन को विफल करने के लिए आप मूल्यों का परीक्षण कर सकते आप प्रत्येक प्रकार बदलाव के लिए सबसे अच्छा योजना प्राप्त कर सकते हैं, के बजाय एक एकल योजना जो आपको पहले उपयोग करने के लिए जो भी प्रकार की विविधता के अनुकूल बनाती है। ,

http://sqlperformance.com/conditional-order-by

+0

+1 अच्छी तरह से काम करता है - सिर्फ उत्सुक क्यों है कि आप केस स्टेटमेंट को गठबंधन नहीं करेंगे? आपके पास 8 है - ऐसा लगता है कि आप 4 को सरल बना सकते हैं? मैं क्या खो रहा हूँ? – sgeddes

+0

@ गॉर्डन लिनॉफ के उत्तर को देखें - मेरा मतलब था और मानदंडों को जोड़ना - अलग-अलग डेटा प्रकारों को वापस नहीं करना ... – sgeddes

+0

@sgeddes ओह हाँ, ठीक है। मैं आमतौर पर उनको विभाजित करता हूं क्योंकि ऐसे मामले हो सकते हैं जहां वे बाद में अंतिम नाम जोड़ते हैं, मिडलनाम, आदि –

15

आप एक मामले बयान की जरूरत है, हालांकि मैं कई मामले बयान का प्रयोग करेंगे:: यह भी हाल ही में एक प्रदर्शन की तुलना मैं भाग गया में सबसे अच्छा प्रदर्शन किया सार्वभौमिक

order by (case when @sortOrder = 'name' and @sortDir = 'asc' then name end) asc, 
     (case when @sortOrder = 'name' and @sortDir = 'desc' then name end) desc, 
     (case when @sortOrder = 'created_date' and @sortDir = 'asc' then created_date end) asc, 
     (case when @sortOrder = 'created_date' and @sortDir = 'desc' then created_date end) desc 

चार अलग-अलग खंड के बाद इस समस्या का निराकरण प्रकारों के बीच परिवर्तित करने के लिए।

+0

जीतते हैं यदि आप दो कॉलम द्वारा ऑर्डर करना चाहते हैं तो क्या होगा? क्या यह केस स्टेटमेंट के साथ संभव है? https://stackoverflow.com/questions/47388230/order-by-two-columns-with-usage-of-case-when/47388327#47388327 – FrenkyB

1
declare @str varchar(max) 
set @str = 'select * from Product order by ' + @sortOrder + ' ' + @sortDir 
exec(@str) 
2

ऐसा करने के कई तरीके हैं। एक तरीका यह होगा:

SELECT * 
FROM 
(
    SELECT 
    ROW_NUMBER() OVER (ORDER BY 
    CASE WHEN @sortOrder = 'name' and @sortDir = 'asc' then name 
    END ASC, 
    CASE WHEN @sortOrder = 'name' and @sortDir = 'desc' THEN name 
    END DESC, 
    CASE WHEN i(@sortOrder = 'created_date' and @sortDir = 'asc' THEN created_date 
    END ASC, 
    CASE WHEN i(@sortOrder = 'created_date' and @sortDir = 'desc' THEN created_date 
    END ASC) RowNum 
    * 
) 
order by 
RowNum 

आप भी इसे गतिशील एसक्यूएल जरिए कर सकते हैं।

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