2011-05-25 4 views
10

मान लीजिए कि मैं उपयोगकर्ता नाम के साथ एक मेज करते हैं:दो प्रश्नों के संघ से शीर्ष एन का चयन कैसे करें जहां परिणामस्वरूप आदेश को व्यक्तिगत क्वेरी द्वारा रैंक किया जाना चाहिए?

Id | Name 
----------- 
1 | Bobby 
20 | Bob 
90 | Bob 
100 | Joe-Bob 
630 | Bobberino 
820 | Bob Junior 

मैं 'बॉब' परिणामस्वरूप जहां सेट के लिए नाम पर n मैचों की एक सूची वापस करना चाहते पहले समान मैचों के बाद सटीक मिलान होता है।

मैंने सोचा था कि कुछ इस तरह

SELECT TOP 4 a.* FROM 
(
    SELECT * from Usernames WHERE Name = 'Bob' 
    UNION 
    SELECT * from Usernames WHERE Name LIKE '%Bob%' 
) AS a 

काम हो सकता है लेकिन वहाँ दो समस्याएं हैं:

  1. यह एक अक्षम क्वेरी के बाद से उप चयन कई पंक्तियों को वापस सकता है (कार्य योजना लागू करके शो को देखकर शीर्ष से पहले होने वाला एक जुड़ना)
  2. (लगभग) अधिक महत्वपूर्ण बात यह है कि सटीक मिलान (एस) परिणाम में पहले दिखाई नहीं देगा क्योंकि परिणामी सेट प्राथमिक कुंजी द्वारा आदेश दिया जाता है।

मैं एक प्रश्न है कि (टॉप 4 के लिए) वापस आ जाएगी किसी एक क्वेरी में

Id | Name 
--------- 
20 | Bob 
90 | Bob 

(and then 2 results from the LIKE query, e.g. 1 Bobby and 100 Joe-Bob) 

यह संभव है के लिए देख रहा हूँ?

उत्तर

10

आप शीर्ष पर सटीक मेल रखने के लिए किसी case इस्तेमाल कर सकते हैं:

select top 4 * 
from Usernames 
where Name like '%Bob%' 
order by 
     case when Name = 'Bob' then 1 else 2 end 

या, यदि आप प्रदर्शन के बारे में चिंतित हैं और (Name) पर एक सूचकांक है:

select top 4 * 
from (
     select 1 as SortOrder 
     ,  * 
     from Usernames 
     where Name = 'Bob' 
     union all 
     select 2 
     ,  * 
     from Usernames 
     where Name like '%Bob%' 
       and Name <> 'Bob' 
       and 4 > 
       (
       select count(*) 
       from Usernames 
       where Name = 'Bob' 
       ) 
     ) as SubqueryAlias 
order by 
     SortOrder 
+0

मुझे आपका समाधान पसंद है। बहुत चालाक! –

+0

अहह! बहुत बढ़िया :) पूरी तरह से केस के बारे में भूल गया ... – Jedidja

3

एक मामूली संशोधन आपकी मूल क्वेरी को हल करना चाहिए। आप एक अतिरिक्त यूनियन में जोड़ सकते हैं जो WHERE Name LIKE 'Bob%' से मेल खाता है और 0 प्राथमिकता दें 0, '%Bob' प्राथमिकता को 3 में बदल रहा है और आपको आईएमएचओ की एक बेहतर खोज मिल जाएगी।

SELECT TOP 4 a.* FROM 
(
    SELECT *, 1 AS Priority from Usernames WHERE Name = 'Bob' 
    UNION 
    SELECT *, 2 from Usernames WHERE Name LIKE '%Bob%' 
) AS a 
ORDER BY Priority ASC 
1

यह बेहतर प्रदर्शन के साथ आप जो चाहते हैं वह कर सकता है।

SELECT TOP 4 a.* FROM 
(
    SELECT TOP 4 *, 1 AS Sort from Usernames WHERE Name = 'Bob' 
    UNION ALL 
    SELECT TOP 4 *, 2 AS Sort from Usernames WHERE Name LIKE '%Bob%' and Name <> 'Bob' 
) AS a 
ORDER BY Sort 
1

यह मेरे लिए काम करता है:

SELECT TOP 4 * FROM (
SELECT 1 as Rank , I, name FROM Foo WHERE Name = 'Bob' 
UNION ALL 
SELECT 2 as Rank,i,name FROM Foo WHERE Name LIKE '%Bob%' 
) as Q1 
ORDER BY Q1.Rank, Q1.I 
1
SET ROWCOUNT 4 

SELECT * from Usernames WHERE Name = 'Bob' 
UNION 
SELECT * from Usernames WHERE Name LIKE '%Bob%' 

SET ROWCOUNt 0 
0

विल एक से जवाब मुझे लाइन पर है, लेकिन मुझे एक त्वरित नोट जोड़ने के लिए, कि तुम कोशिश कर रहे हैं करना चाहते हैं एक ही चीज़ करने के लिए और "एक्सएमएल पथ के लिए" शामिल करने के लिए, आपको इसे थोड़ा अलग लिखना होगा।

मैं XML गुणधर्मों को निर्दिष्ट किया गया था और इसलिए तरह बातें था:

SELECT Field_1 as [@attr_1] 

क्या आप उप प्रश्नों में "@" प्रतीक को हटा दें और फिर उन्हें वापस जोड़ें बाहरी क्वेरी के साथ में है क्या करना है। इस तरह:

SELECT top 1 a.SupervisorName as [@SupervisorName] 
FROM 
(
    SELECT (FirstNames + ' ' + LastName) AS [SupervisorName],1 as OrderingVal 
    FROM ExamSupervisor SupervisorTable1 

    UNION ALL 

    SELECT (FirstNames + ' ' + LastName) AS [SupervisorName],2 as OrderingVal 
    FROM ExamSupervisor SupervisorTable2 

) as a 
ORDER BY a.OrderingVal ASC 
FOR XML PATH('Supervisor') 

यह मेरा अंतिम प्रश्न का एक कट नीचे संस्करण है, तो यह वास्तव में कोई मतलब नहीं है, लेकिन आप विचार प्राप्त करना चाहिए।

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