ส่งคืนค่าหากไม่พบแถวใน Microsoft tSQL


97

ใช้SQL เวอร์ชันMicrosoftนี่คือแบบสอบถามง่ายๆของฉัน หากฉันสอบถามบันทึกที่ไม่มีอยู่ฉันจะไม่ได้รับสิ่งใดกลับคืนมา ฉันต้องการให้ส่งคืนเท็จ (0) ในสถานการณ์นั้น กำลังมองหาวิธีการที่ง่ายที่สุดในการไม่บันทึกข้อมูล

SELECT  CASE
            WHEN S.Id IS NOT NULL AND S.Status = 1 AND (S.WebUserId = @WebUserId OR S.AllowUploads = 1) THEN 1
            ELSE 0
        END AS [Value]

        FROM Sites S

        WHERE S.Id = @SiteId

คำตอบ:


67
SELECT CASE WHEN COUNT(1) > 0 THEN 1 ELSE 0 END AS [Value]

FROM Sites S

WHERE S.Id = @SiteId and S.Status = 1 AND 
      (S.WebUserId = @WebUserId OR S.AllowUploads = 1)

ด้านล่างแบบสอบถามจะส่งคืนค่าเดียวในเงื่อนไขอื่น แต่ควรส่งคืนค่าหลายค่า เลือกกรณีที่นับ (QTIB_REQ _) <1 จากนั้น 0 อื่น QTIB_REQ_ สิ้นสุดจาก qb_requisitions_all โดยที่ QTIB_REQ_ IN ($ Req_disabled_WA) และ CLIENT___BENCH___NON_BILLABLE NOT IN ('Non Billable', 'Non-Billable', 'NonBillable', 'NonBillable', 'NonBillable', 'NonBillable' SC เคลียร์การจ้างงานเชิงกลยุทธ์ ',' Bench / US project ') และ DATEDIFF (CURDATE (), TARGET_FILL_DATE) <60 และ DATEDIFF (CURDATE (), TARGET_FILL_DATE)> 0
Praneet Bahadur

128

คล้ายกับ Adam Robinson แต่ใช้ ISNULL แทน COUNT

SELECT ISNULL(
(SELECT 1 FROM Sites S
WHERE S.Id = @SiteId and S.Status = 1 AND 
      (S.WebUserId = @WebUserId OR S.AllowUploads = 1)), 0)

หากแบบสอบถามภายในมีแถวที่ตรงกันระบบจะส่งคืน 1 แบบสอบถามภายนอก (ที่มี ISNULL) จะส่งกลับค่านี้เป็น 1 หากแบบสอบถามด้านในไม่มีแถวที่ตรงกันจะไม่ส่งคืนอะไรเลย แบบสอบถามภายนอกถือว่าสิ่งนี้เป็นค่าว่างดังนั้น ISNULL จึงส่งกลับ 0


2
ขอบคุณที่เพิ่มอันนี้! มันคือสิ่งที่ฉันต้องการอย่างที่ฉันสามารถทำได้เพียงแค่เลือก ISNULL ((SELECT Id ... แทนที่จะเป็น 1 เพื่อรับข้อมูลที่ฉันกำลังมองหา!
Jesse Smith

3
สายมากฉันรู้ แต่คุณสามารถแทนที่ ISNULL ด้วย COALESCE เพื่อให้ได้ผลลัพธ์เดียวกัน
BlueChippy

2
ฉันติดนิสัยในการใช้ COALESCE มากกว่า ISNULL เพราะจากความจำ (นิสัยตายยาก) ISNULL ไม่มีใน SQL Lite หรืออะไรก็ตามที่เรียกว่าทำงานบนอุปกรณ์ Windows Mobile รุ่นเก่า COALESCE ทำงานได้กับ SQL ทั้งแบบไลต์ Express และแบบเต็ม
โฆษณา

1
จะได้ผลดีกว่าถ้าคุณต้องการรับค่าตัวแปรแทนที่จะเป็น 0 หรือ 1 คิวรีของอดัมต้องการการจัดกลุ่มหรืออะไรทำนองนั้น
Drac

@MoeSisko ฉันชอบวิธีที่มันคืนค่า 0 ถ้ามันเป็นโมฆะ แต่แทนที่จะคืนค่า 1 ฉันจะให้มันคืนค่าจากตารางได้อย่างไร
Michael

21

นี่อาจเป็นม้าตายอีกวิธีหนึ่งในการส่งคืน 1 แถวเมื่อไม่มีแถวอยู่คือการค้นหา UNION อื่นและแสดงผลลัพธ์เมื่อไม่มีอยู่ในตาราง

SELECT S.Status, COUNT(s.id) AS StatusCount
FROM Sites S
WHERE S.Id = @SiteId
GROUP BY s.Status
UNION ALL --UNION BACK ON TABLE WITH NOT EXISTS
SELECT 'N/A' AS Status, 0 AS StatusCount
WHERE NOT EXISTS (SELECT 1
   FROM Sites S
   WHERE S.Id = @SiteId
) 

2
ฉันใช้วิธีการที่คล้ายกันนี้เมื่อพยายามรับผลรวมจากแบบสอบถาม ฉันแค่ทำการยูเนี่ยนด้วยคิวรีที่ส่งกลับ 0 ( SELECT 0) จากนั้นฉันก็ทำการSUMยูเนี่ยน ง่ายและสะดวกในการติดตาม
cjbarth

2
ถ้าส่งคืน 2 แถวรับประกันว่าจะส่งคืนแถวตามลำดับที่คาดไว้หรือไม่?
Sarsaparilla

และมันหนักไปที่แผนการดำเนินการ
Fandango68

12

สิ่งที่ต้องการ:

if exists (select top 1 * from Sites S where S.Id IS NOT NULL AND S.Status = 1 AND (S.WebUserId = @WebUserId OR S.AllowUploads = 1))
    select 1
else
    select 0

ฉันใช้วิธีนี้เพราะมันสมเหตุสมผลสำหรับฉันมากขึ้น (ฉันไม่ได้เป็นผู้ใช้ SQL แบบดั้งเดิม) อย่างไรก็ตามฉันใช้ SQL Server ฉันพบว่าการเพิ่มชื่อ col ในสิ่งนี้ทำให้โซลูชันนี้โค้งมนได้ดี เช่นหลังจากคุณselect 1และselect 2ฉันเพิ่มas <colName>
Harvey

8

ฉันอ่านคำตอบทั้งหมดที่นี่และใช้เวลาสักพักในการคิดว่าเกิดอะไรขึ้น ต่อไปนี้เป็นไปตามคำตอบของMoe Siskoและงานวิจัยที่เกี่ยวข้อง

ถ้าแบบสอบถาม SQL ของคุณไม่ส่งคืนข้อมูลใด ๆ จะไม่มีฟิลด์ที่มีค่าว่างดังนั้น ISNULL หรือ COALESCE จะไม่ทำงานตามที่คุณต้องการ ด้วยการใช้แบบสอบถามย่อยแบบสอบถามระดับบนสุดจะได้รับเขตข้อมูลที่มีค่าว่างและทั้ง ISNULL และ COALESCE จะทำงานตามที่คุณต้องการ / คาดหวัง

คำถามของฉัน

select isnull(
 (select ASSIGNMENTM1.NAME
 from dbo.ASSIGNMENTM1
 where ASSIGNMENTM1.NAME = ?)
, 'Nothing Found') as 'ASSIGNMENTM1.NAME'

คำถามของฉันพร้อมความคิดเห็น

select isnull(
--sub query either returns a value or returns nothing (no value)
 (select ASSIGNMENTM1.NAME
 from dbo.ASSIGNMENTM1
 where ASSIGNMENTM1.NAME = ?)
 --If there is a value it is displayed 
 --If no value, it is perceived as a field with a null value, 
 --so the isnull function can give the desired results
, 'Nothing Found') as 'ASSIGNMENTM1.NAME'

5

คุณต้องแทนที่ WHERE ด้วย LEFT JOIN เท่านั้น:

SELECT  CASE
        WHEN S.Id IS NOT NULL AND S.Status = 1 AND ...) THEN 1
        ELSE 0
    END AS [Value]

    FROM (SELECT @SiteId AS Id) R
    LEFT JOIN Sites S ON S.Id = R.Id

โซลูชันนี้ช่วยให้คุณสามารถคืนค่าเริ่มต้นสำหรับแต่ละคอลัมน์ได้เช่นกัน:

SELECT
    CASE WHEN S.Id IS NULL THEN 0 ELSE S.Col1 END AS Col1,
    S.Col2,
    ISNULL(S.Col3, 0) AS Col3
FROM
    (SELECT @Id AS Id) R
    LEFT JOIN Sites S ON S.Id = R.Id AND S.Status = 1 AND ...

4

ไม่มีระเบียนที่ตรงกันหมายความว่าไม่มีการส่งคืนระเบียน ไม่มีที่สำหรับ "ค่า" ของ 0 ที่จะไปหากไม่พบบันทึก คุณสามารถสร้างคำค้นหา UNION ที่บ้าคลั่งเพื่อทำสิ่งที่คุณต้องการ แต่ดีกว่ามากเพียงแค่ตรวจสอบจำนวนระเบียนในชุดผลลัพธ์


ปัจจุบันนั่นคือสิ่งที่ฉันทำ ตรวจสอบจำนวนบันทึกว่าว่างเปล่าหรือไม่ คิดว่าอาจเป็นวิธีลัดเช็คของฉัน
แมตต์

แอปบางแอปไม่อนุญาตให้คุณตรวจสอบ "อย่างเดียว"
Nadia Solovyeva

3

นี่อาจเป็นวิธีหนึ่ง

SELECT TOP 1 [Column Name] FROM (SELECT [Column Name] FROM [table]
    WHERE [conditions]
    UNION ALL
    SELECT 0 )A ORDER BY [Column Name] DESC

ฉันชอบแนวทางนี้ ฉันรู้สึกว่ามันค่อนข้างสะอาดกว่าเมื่อแสดงข้อมูลเริ่มต้นโดยเฉพาะอย่างยิ่งถ้าคุณลงเอยด้วยคอลัมน์ข้อมูล / ค่าเริ่มต้นจำนวนมาก
Mark At Ramp51

ฮ่า ๆ นี่เป็นทางออกที่ดีและสะอาดที่สุด
Kyle Bridenstine

1

แล้ว TIES ล่ะ?

SELECT TOP 1 WITH TIES tbl1.* FROM 
        (SELECT CASE WHEN S.Id IS NOT NULL AND S.Status = 1 
                      AND (S.WebUserId = @WebUserId OR 
                           S.AllowUploads = 1)
                     THEN 1 
                     ELSE 0 AS [Value]
         FROM Sites S
         WHERE S.Id = @SiteId) as tbl1
ORDER BY tbl1.[Value]


1

คำตอบของ @ hai-phan LEFT JOINเป็นกุญแจสำคัญ แต่อาจจะยากที่จะปฏิบัติตาม ฉันมีคำถามที่ซับซ้อนซึ่งอาจไม่ส่งคืนอะไรเลย ฉันแค่ทำให้คำตอบของเขาง่ายขึ้นสำหรับความต้องการของฉัน ง่ายต่อการนำไปใช้กับแบบสอบถามที่มีหลายคอลัมน์

;WITH CTE AS (
  -- SELECT S.Id, ...
  -- FROM Sites S WHERE Id = @SiteId
  -- EXCEPT SOME CONDITION.
  -- Whatever your query is
)
SELECT CTE.* -- If you want something else instead of NULL, use COALESCE.
FROM (SELECT @SiteId AS ID) R
LEFT JOIN CTE ON CTE.Id = R.ID

อัปเดต: คำตอบนี้ใน SqlServerCentralดีที่สุด โดยใช้คุณลักษณะนี้ของ MAX - "MAX จะคืนค่า NULL เมื่อไม่มีแถวให้เลือก"

SELECT ISNULL(MAX(value), 0) FROM table WHERE Id = @SiteId

1
คำตอบที่อัปเดตใช้งานได้
Andrew Cowenhoven

0
You should avoid using expensive methods. You dont need any column for TBL2. 

SELECT COUNT(*) FROM(
         SELECT TOP 1     1 AS CNT  FROM  TBL1 
         WHERE ColumnValue ='FooDoo'  ) AS TBL2

or

IF EXISTS (SELECT TOP 1 1 FROM TABLE1 AS T1 
                          WHERE T1.ColumnValue='VooDoo') 
   SELECT 1 
ELSE 
   SELECT 0

0

คุณสามารถทำสิ่งนี้ได้

IF EXISTS ( SELECT * FROM TableName WHERE Column=colval)
BEGIN
   select 
select name ,Id from TableName WHERE Column=colval
END
ELSE
  SELECT 'test' as name,0 as Id
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.