Microsoft tSQLで行が見つからない場合は値を返します


95

使用するマイクロソフトの SQLのバージョンを、ここに私の単純なクエリです。存在しないレコードをクエリすると、何も返されません。そのシナリオではfalse(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

回答:


64
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)

以下のクエリはelse条件で単一の値を返しますが、理想的には複数の値を返す必要があります。count(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'、 'Bench SCが「戦略的採用」、「ベンチ/米国プロジェクト」をクリア)およびDATEDIFF(CURDATE()、TARGET_FILL_DATE)<60およびDATEDIFF(CURDATE()、TARGET_FILL_DATE)> 0
Praneet Bahadur

121

これはAdam Robinsonのものに似ていますが、COUNTではなくISNULLを使用します。

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を返します。内部クエリに一致する行がない場合、何も返しません。外部クエリはこれをNULLのように扱うため、ISNULLは最終的に0を返します。


2
これを追加してくれてありがとう!!私はちょうど私が探していたデータを取得する代わりに、1のISNULL((SELECT同上...選択できるように、それは、私が必要とするまさにだ
ジェシー・スミス

3
非常に遅いですが、ISNULLをCOALESCEに置き換えて同じ結果を得ることができます。
BlueChippy 2013年

2
ISNULLではなくCOALESCEを使用する習慣になりました。これは、メモリから(習慣が困難になるため)、SQL Liteまたはそれより古いWindows Mobileデバイスで実行されると呼ばれるものではISNULLを使用できないためです。COALESCEは、Lite、Express、および本格的なSQLの両方で動作します。
広告

1
0または1の代わりに変数値を取得する場合は、より適切に機能します。Adamのクエリには、グループ化などが必要です。
Drac、2015

@MoeSisko nullの場合に0を返す方法が好きですが、1を返す代わりに、テーブルから値を返すにはどうすればよいですか?
マイケル

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)を返すクエリでユニオンを実行し、次にユニオンでaを実行しSUMました。シンプルでわかりやすい。
cjbarth

2
2行を返す場合、行が期待どおりの順序で返されることが保証されますか?
Sarsaparilla、2015年

そして、それは実行計画に重い
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 1select 2私が追加した後as <colName>
Harvey

8

私はここですべての答えを読み、何が起こっているのかを理解するのにしばらく時間がかかりました。以下は、答えに基づいています Moe Siskoのといくつかの関連研究に

SQLクエリがデータを返さない場合は、null値のフィールドがないため、ISNULLもCOALESCEも期待どおりに機能しません。サブクエリを使用すると、トップレベルのクエリはnull値のフィールドを取得し、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クエリを作成して、必要なことを実行できますが、結果セットのレコード数を確認するだけではるかに優れています。


現在、それが私の仕事です。レコード数が空かどうかを確認します。彼らは私のチェックをショートカットする方法であるかもしれないと考えました。
マット

一部のアプリでは「単純に」チェックできません
ナディアソロビエバ

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

笑これは最高で最もクリーンなソリューションです
カイル・ブリデンスティン

1

WITH 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
DECLARE @col int; 
select @col = id  FROM site WHERE status = 1; 
select coalesce(@col,0);

0

@ 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

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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.