programing

행을 반환하지 않는 쿼리의 기본 행을 설정하는 방법은 무엇입니까?

powerit 2023. 11. 4. 13:24
반응형

행을 반환하지 않는 쿼리의 기본 행을 설정하는 방법은 무엇입니까?

테이블에 행이 없는 경우 기본 행을 반환하는 방법을 알아야 합니다.이것을 하는 가장 좋은 방법은 무엇입니까?저는 가치를 얻기 위해 이 특정 테이블에서 한 열만 반환할 뿐입니다.

편집: SQL Server 입니다.

Oracle을 위한 한 가지 접근 방식:

SELECT val
FROM myTable
UNION ALL
SELECT 'DEFAULT'
FROM dual
WHERE NOT EXISTS (SELECT * FROM myTable)

또는 Oracle의 경우:

SELECT NVL(MIN(val), 'DEFAULT')
FROM myTable

또는 SqlServer에서:

SELECT ISNULL(MIN(val), 'DEFAULT')
FROM myTable

이것들은 이 사실을 이용합니다.MIN()돌아온다NULL줄이 없을 때는

기본 쿼리가 한 행만 반환할 것으로 예상되는 경우 다음과 같은 방법을 사용할 수 있습니다.

select NVL( MIN(rate), 0 ) AS rate 
from d_payment_index
where fy = 2007
  and payment_year = 2008
  and program_id = 18

(Oracle 코드, NVL이 SQL Server에 적합한 기능인지 확실하지 않음)

이렇게 하면 선택 쿼리를 두 번 실행할 수 없게 되고 성능도 향상됩니다.

Declare @rate int

select 
    @rate = rate 
from 
    d_payment_index
where 
    fy = 2007
    and payment_year = 2008
    and program_id = 18

IF @@rowcount = 0
    Set @rate = 0

Select @rate 'rate'

이거 어때:

SELECT DEF.Rate, ACTUAL.Rate, COALESCE(ACTUAL.Rate, DEF.Rate) AS UseThisRate
FROM 
  (SELECT 0) DEF (Rate) -- This is your default rate
LEFT JOIN (
  select rate 
  from d_payment_index
  --WHERE 1=2   -- Uncomment this line to simulate a missing value

  --...HERE IF YOUR ACTUAL WHERE CLAUSE. Removed for testing purposes...
  --where fy = 2007
  -- and payment_year = 2008
  --  and program_id = 18
) ACTUAL (Rate) ON 1=1

결과.

유효한 요금이 존재

Rate        Rate        UseThisRate
----------- ----------- -----------
0           1           1

기본 사용률

Rate        Rate        UseThisRate
----------- ----------- -----------
0           NULL        0

테스트 DDL

CREATE TABLE d_payment_index (rate int NOT NULL)
INSERT INTO d_payment_index VALUES (1)

이 토막글에서는 공통 테이블 표현식을 사용하여 중복 코드를 줄이고 가독성을 높입니다.이것은 존 보먼의 대답을 변형한 것입니다.

구문은 SQL Server에 대한 것입니다.

WITH products AS (
            SELECT prod_name,
                   price
              FROM Products_Table
             WHERE prod_name LIKE '%foo%'
     ),
     defaults AS (
            SELECT '-' AS prod_name,
                   0   AS price
     )

SELECT * FROM products
UNION ALL
SELECT * FROM defaults
 WHERE NOT EXISTS ( SELECT * FROM products );

*SQL 솔루션

기본 키가 "id"인 리뷰 테이블이 있다고 가정합니다.

SELECT * FROM review WHERE id = 1555
UNION ALL
SELECT * FROM review WHERE NOT EXISTS ( SELECT * FROM review where id = 1555 ) AND id = 1

테이블에 1555 id의 리뷰가 없다면 이 쿼리는 id 1의 리뷰를 제공할 것입니다.

제가 알아냈는데, 다른 시스템에서도 작동이 될 겁니다.WW의 답변을 변형한 것입니다.

select rate 
from d_payment_index
where fy = 2007
  and payment_year = 2008
  and program_id = 18
union
select 0 as rate 
from d_payment_index 
where not exists( select rate 
                  from d_payment_index
                  where fy = 2007
                    and payment_year = 2008
                    and program_id = 18 )

기본값에서 실제값으로 왼쪽 조인을 사용하는 하나의 테이블 스캔 방법:

CREATE TABLE [stackoverflow-285666] (k int, val varchar(255))

INSERT  INTO [stackoverflow-285666]
VALUES  (1, '1-1')
INSERT  INTO [stackoverflow-285666]
VALUES  (1, '1-2')
INSERT  INTO [stackoverflow-285666]
VALUES  (1, '1-3')
INSERT  INTO [stackoverflow-285666]
VALUES  (2, '2-1')
INSERT  INTO [stackoverflow-285666]
VALUES  (2, '2-2')

DECLARE @k AS int
SET @k = 0

WHILE @k < 3
    BEGIN
        SELECT  @k AS k
               ,COALESCE(ActualValue, DefaultValue) AS [Value]
        FROM    (
                 SELECT 'DefaultValue' AS DefaultValue
                ) AS Defaults
        LEFT JOIN (
                   SELECT   val AS ActualValue
                   FROM     [stackoverflow-285666]
                   WHERE    k = @k
                  ) AS [Values]
                ON 1 = 1

        SET @k = @k + 1
    END

DROP TABLE [stackoverflow-285666]

출력:

k           Value
----------- ------------
0           DefaultValue

k           Value
----------- ------------
1           1-1
1           1-2
1           1-3

k           Value
----------- ------------
2           2-1
2           2-2

테이블이 있다고 가정할 때config독특한 색인으로config_code열:

CONFIG_CODE     PARAM1   PARAM2
--------------- -------- --------
default_config  def      000
config1         abc      123
config2         def      456

이 쿼리는 다음에 대한 줄을 반환합니다.config1테이블에 존재하므로 값:

SELECT *
  FROM (SELECT *
          FROM config
         WHERE config_code = 'config1'
            OR config_code = 'default_config'
         ORDER BY CASE config_code WHEN 'default_config' THEN 999 ELSE 1 END)
 WHERE rownum = 1;
CONFIG_CODE     PARAM1   PARAM2
--------------- -------- --------
config1         abc      123

이 레코드는 다음과 같이 기본 레코드를 반환합니다.config3테이블에 존재하지 않습니다.

SELECT *
  FROM (SELECT *
          FROM config
         WHERE config_code = 'config3'
            OR config_code = 'default_config'
         ORDER BY CASE config_code WHEN 'default_config' THEN 999 ELSE 1 END)
 WHERE rownum = 1;
CONFIG_CODE     PARAM1   PARAM2
--------------- -------- --------
default_config  def      000

다른 솔루션과 비교하여 이 하나의 쿼리 테이블config단 한 번

전체 행을 반환하시겠습니까?기본 행에 기본값이 있어야 합니까 아니면 빈 행이 될 수 있습니까?기본 행의 열 구조가 문제의 테이블과 같도록 하시겠습니까?

요구 사항에 따라 다음과 같은 작업을 수행할 수 있습니다.

1) 쿼리를 실행하고 결과를 임시 테이블(또는 테이블 변수)에 넣습니다. 2) 임시 테이블에 결과가 있는지 확인합니다. 3) 그렇지 않은 경우 이와 유사한 선택 문을 수행하여 빈 행을 반환합니다(SQL Server에서).

select '' as columnA, '' as columnB, '' as columnC from #tempTable

여기서 열 A, 열 B 및 열 C는 실제 열 이름입니다.

테이블 변수에 기본값을 삽입한 다음 이 tableVar의 단일 행을 실제 테이블과 일치시키는 것으로 업데이트합니다.행이 발견되면 tableVar가 업데이트되고, 발견되지 않으면 기본값이 유지됩니다.테이블 변수를 반환합니다.

    ---=== The table & its data
    CREATE TABLE dbo.Rates (
        PkId int,
        name varchar(10),
        rate decimal(10,2)
    )
    INSERT INTO dbo.Rates(PkId, name, rate) VALUES (1, 'Schedule 1', 0.1)
    INSERT INTO dbo.Rates(PkId, name, rate) VALUES (2, 'Schedule 2', 0.2)

해결책은 다음과 같습니다.

---=== The solution 
CREATE PROCEDURE dbo.GetRate 
  @PkId int
AS
BEGIN
  DECLARE @tempTable TABLE (
    PkId int, 
    name varchar(10), 
    rate decimal(10,2)
 )

 --- [1] Insert default values into @tempTable. PkId=0 is dummy value  
 INSERT INTO @tempTable(PkId, name, rate) VALUES (0, 'DEFAULT', 0.00)

 --- [2] Update the single row in @tempTable with the actual value.
 ---     This only happens if a match is found
 UPDATE @tempTable
    SET t.PkId=x.PkId, t.name=x.name, t.rate = x.rate
    FROM @tempTable t INNER JOIN dbo.Rates x
    ON t.PkId = 0
    WHERE x.PkId = @PkId

 SELECT * FROM @tempTable
END

코드 테스트:

EXEC dbo.GetRate @PkId=1     --- returns values for PkId=1
EXEC dbo.GetRate @PkId=12314 --- returns default values

값이 없는 경우 기본값을 얻을 때 사용한 값입니다.


    SELECT IF (
        (SELECT COUNT(*) FROM tbs.replication_status) > 0, 
        (SELECT rs.last_replication_end_date FROM tbs.replication_status AS rs 
            WHERE rs.last_replication_start_date IS NOT NULL 
                AND rs.last_replication_end_date IS NOT NULL 
                AND rs.table = '%s' ORDER BY id DESC LIMIT 1), 
        (SELECT CAST(UNIX_TIMESTAMP (CURRENT_TIMESTAMP(6)) AS UNSIGNED))
    ) AS ts;

언급URL : https://stackoverflow.com/questions/285666/how-to-set-a-default-row-for-a-query-that-returns-no-rows

반응형