WHERE क्लॉज के लिए वैकल्पिक [बंद]


16

क्या SELECTबिना उपयोग किए, किसी कॉलम में केवल निश्चित डेटा वाली पंक्तियों का एक तरीका है WHERE?

उदाहरण के लिए यदि मेरे पास यह था:

SELECT * FROM Users
WHERE town = 'Townsville'

क्या कथन WHEREमें खंड को लागू करने का कोई तरीका है SELECT?

कुछ इस तरह

SELECT *, town('Townsville') FROM Users

यह एक विचित्र सवाल है, लेकिन यह एक है जो मैंने अपने साथियों से पूछा है


4
उनसे पूछें कि वे ऐसा क्यों पूछ रहे हैं। प्रसंग महत्वपूर्ण है।
हारून बर्ट्रेंड

@AaronBertrand, MikaelEriksson - मूल रूप से यह काम पर SQL के बारे में एक छोटी सी प्रश्नावली है, मुझे एक सवाल आया है जिसमें कहा गया है "Townsville से आने वाले उपयोगकर्ता तालिका से सभी उपयोगकर्ताओं का चयन करें, जहां एक ठहराव का उपयोग किए बिना" और, मुझे नहीं पता था कि संभव था! शायद मैं इस गलत तरीके से आ रहा हूं ..?
जोश स्टीवेंसन

यह भी बताते हुए कि यह प्रश्नावली किसी भी तरह से कंपनी के साथ मेरे रोजगार की स्थिति से जुड़ी हुई नहीं है! यह मजेदार सा है
जोश स्टीवेंसन

जवाबों:


17

यकीन नहीं हो रहा है कि यह उस तरह की पागल चीज है जिसकी आपको तलाश थी ...।

अस्वीकरण : मुझे बिल्कुल पता नहीं है कि आप इसका उपयोग क्यों करना चाहते हैं।

SELECT * 
FROM Users AS u
INNER JOIN (SELECT 'Townsville' town) towns 
  ON towns.town = u.Town;

17

डेटा

DECLARE @Example AS table
(
    UserName varchar(30) NULL,
    Town varchar(30) NULL
);

INSERT @Example
    (UserName, Town)
VALUES
    ('Aaron', 'Not Townsville'),
    ('Bob', 'Not Townsville'),
    ('Charles', 'Townsville'),
    ('Charles', 'Townsville'),
    ('Charles', 'Townsville'),
    ('Charles', 'Townsville'),
    ('Dan', 'Townsville'),
    ('Eric', 'Not Townsville');

वैकल्पिक समाधान

SELECT E.UserName, E.Town
FROM @Example AS E
GROUP BY E.Town, E.UserName
HAVING E.Town = 'Townsville'

-- OR

SELECT E.UserName, 'Townsville' AS Town
FROM @Example AS E
GROUP BY E.UserName
HAVING 1 = MAX(CASE WHEN E.Town = 'Townsville' THEN 1 ELSE 0 END);

-- OR

SELECT E.UserName, E.Town
FROM @Example AS E
INTERSECT
SELECT E.UserName, 'Townsville' AS Town
FROM @Example AS E

डुप्लिकेट को बनाए रखना

-- :)
SELECT E.UserName, E.Town
FROM @Example AS E
CROSS APPLY (VALUES(NEWID())) AS CA (n)
GROUP BY E.Town, E.UserName, CA.n
HAVING E.Town = 'Townsville'

-- Simulating INTERSECT ALL
SELECT
    R.UserName,
    R.Town
FROM 
(
    SELECT 
        E.UserName, 
        E.Town, 
        rn =
            ROW_NUMBER() OVER (
                PARTITION BY E.UserName, E.Town 
                ORDER BY E.UserName, E.Town)
    FROM @Example AS E
    INTERSECT
    SELECT 
        E.UserName, 
        'Townsville', 
        rn = 
        ROW_NUMBER() OVER (
            PARTITION BY E.UserName 
            ORDER BY E.UserName)
    FROM @Example AS E
) AS R;

आउटपुट:

╔══════════╦════════════╗
 UserName     Town    
╠══════════╬════════════╣
 Charles   Townsville 
 Dan       Townsville 
╚══════════╩════════════╝

अंतिम उदाहरण के लिए:

╔══════════╦════════════╗
 UserName     Town    
╠══════════╬════════════╣
 Charles   Townsville 
 Charles   Townsville 
 Charles   Townsville 
 Charles   Townsville 
 Dan       Townsville 
╚══════════╩════════════╝

इसे यहाँ आज़माएँ: Stack Exchange Data Explorer


बहुत अच्छा! मैं अनुमान लगा रहा हूं कि मैं इस परिदृश्य में इसका उपयोग नहीं कर पाऊंगा, जहां मेरे पास केवल अनन्य डेटा जैसे 'उपयोगकर्ता नाम' वाला कॉलम नहीं है? जैसे अगर मेरे पास केवल नाम, उपनाम, शहर होता।
जोश स्टीवेंसन

3
@JoshStevenson सही है, हालांकि मैंने डुप्लिकेट को अंतिम उदाहरण के रूप में संरक्षित करने के लिए एक पागल तरीके से जोड़ा, और फिर एक समझदार।
पॉल व्हाइट को फिर से बहाल मोनिका

1
के लिए GROUP BYसमाधान, आप भी पी समूह में सूची से जोड़ सकता है (यकीन है कि 100% है कि प्रश्नों जहां के रूप में पंक्तियों की एक ही नंबर वापसी)। यह मानते हुए कि एक PK है;)
ypercube


14

"सिर्फ मनोरंजन के लिए" आप एक के order byसाथ उपयोग कर सकते हैंtop(1) with ties

select top(1) with ties *
from dbo.Users
order by case when town = 'Townsville' then 1 else 2 end;

यह Townsvilleमामला वापस आने के बाद पहली बार सभी पंक्तियों को आदेश देगा1यदि तोtown = 'Townsville' । अन्य सभी पंक्तियों 2के मामले में वापसी होगी ।

with tiesखंड क्वेरी सभी पंक्तियों पंक्तियों लौटे में अंतिम स्थान के लिए एक "टाई" है कि वापसी बनाता है। इसके top(1)साथ संयोजन में उपयोग करने से with tiesसभी पंक्तियाँ वापस आ जाएंगी, जिनका मान खंड में क्रम में प्रयुक्त पहली पंक्ति के समान होता है।

ध्यान दें, जैसा कि मार्टिन स्मिथ ने एक टिप्पणी में बताया है, यह वापस आ जाएगा यदि आप एक ऐसे शहर की मांग करते हैं जो तालिका में मौजूद नहीं है सभी पंक्तियों

यदि आप डेटाबेस की XML चीजों से डरते नहीं हैं, तो आप नोड्स () फ़ंक्शन में एक विधेय का उपयोग कर सकते हैं।

पॉल व्हाइट से सेटअप उधार लेना।

select T.X.value('(UserName/text())[1]', 'varchar(30)') as UserName,
       T.X.value('(Town/text())[1]', 'varchar(30)') as Town
from (
     select *
     from @Example
     for xml path('row'), type 
     ) as C(X)
  cross apply C.X.nodes('/row[Town = "Townsville"]') as T(X);

किसी अन्य संस्करण के साथ topऔर order byवह वास्तव में तब काम करता है जब मौजूदा कस्बों के लिए नहीं।

select top(
          select sum(case when town = 'Townsville' then 1 end)
          from @Example
          ) *
from @Example
order by case when town = 'Townsville' then 1 else 2 end

7

आपके पास यहां दो अलग चीजें हैं।

SELECT * FROM Users
WHERE town = 'Townsville'

उन पंक्तियों की संख्या को सीमित कर देगा जो आपको वापस वहीं मिलती हैं जहाँ शहर =Townsville

SELECT *, town('Townsville') FROM Users

शाब्दिक पारित करने के Townsvilleलिए एक समारोह कहा जाता हैtown । यह क्वेरी द्वारा लौटाए गए पंक्तियों को प्रतिबंधित नहीं करेगा और वास्तव में यदि फ़ंक्शन कुछ भी लौटाता है, लेकिन एक एकल मान आपको एक त्रुटि मिलेगा।

क्वेरी से वापस मिलने वाली पंक्तियों की संख्या को प्रतिबंधित करने के अन्य तरीके हैं। उदाहरण के लिए HAVING खंड। लेकिन इसकी कई अन्य आवश्यकताएं हैं।

SELECT town FROM Users
GROUP BY town
HAVING town = 'Townsville'

या एक INNER JOIN करें हालाँकि यह एक अजीब सा है अगर आपके पास दूसरा टेबल नहीं है।

SELECT * FROM Users
INNER JOIN (SELECT 1 col1) UselessTable
    ON Users.town = 'Townsville'

5

यहां एक सामान्य तालिका अभिव्यक्ति (CTE) का उपयोग करके एक उदाहरण दिया गया है।

with Town as 
(
    select 'Townsville' as Town
)
select *
  from Users u
  join Town  t on u.Town = t.Town

5

वैसे आप ऐसा कर सकते हैं:

    SELECT A.* 
    FROM Users A
         INNER JOIN Users B ON A.Id = B.Id AND B.town = 'Townsville'

कड़ाई से बोल रहे हैं कि आप WHERE क्लॉज का उपयोग नहीं कर रहे हैं


5

यहाँ एक है मूर्खतापूर्ण यह करने के लिए है कि मैं अभी तक नहीं दिख रहा है पूरी तरह से तार्किक ढंग से ....

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;  -- Our important work should be all the database cares about
GO
BEGIN TRANSACTION

DECLARE @MyTableVar table(<all columns in order from the user table>, oldtown VARCHAR(50));

UPDATE users
SET town = N'Townsville'
OUTPUT 
     inserted.*  -- We don't want to have to type out the columns because that would be too much work
    deleted.town
INTO @MyTableVar;

--Display the result set of the table variable to prevent undesirables from sullying our output by inserting incorrect data even though we should have exclusive access.
SELECT * -- Select everything we want except for the 'oldtown' column because that data was probably wrong anyway
FROM @MyTableVar;

UPDATE u -- We don't want to be bad stewards of our data
SET
    town = oldtown
FROM users u
    INNER JOIN @MyTableVar mtv ON mtv.town = u.town, <Match up all the columns to REALLY ensure we are matching the proper row>

COMMIT TRANSACTION -- Make sure we save our work

मैं कल्पना नहीं कर सकता कि यह पहली बात क्यों नहीं सुझाई गई। :)


-2
SELECT *, 
    case when town='Townsville' then 'Townsville' 
         else null 
    end as Town
FROM Users

Townsville के अलावा सभी शहर अशक्त होंगे। समस्या सुलझ गयी।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.