Как можно сжать несколько операторов SELECT в один, если значение основано на значении в другом столбце? - PullRequest
2 голосов
/ 22 февраля 2020

Из внешнего интерфейса XML отправляется в хранимую процедуру, которая анализирует ее во временную таблицу с двумя столбцами:

 | DataName | DataValue |
1| blahblah | datadata  |
2|    ...   |    ...    |
3|    ...   |    ...    |
4|    ...   |    ...    |

Из этой временной таблицы я устанавливаю значение в DataValue - переменная на основе строки в столбце DataName. Например:

SELECT @blahblah= IsNull(DataValue,0)
        FROM #XMLTempTable
        WHERE DataName = 'blahblah'

SELECT @userid = IsNull(DataValue,0)
        FROM #XMLTempTable
        WHERE DataName = 'userid'

SELECT @value = IsNull(DataValue,0)
        FROM #XMLTempTable
        WHERE DataName = 'value'

Есть ли лучший способ выбрать значения из временной таблицы, а не по одному, как я делаю?

Ответы [ 3 ]

3 голосов
/ 22 февраля 2020

Если вы пытаетесь «разворачивать» эти пары ключ / значение в более значимые строки, возможно, это вам поможет. Тем не менее, обратите внимание, что предполагать, что любой порядок строк в таблице sql является плохой идеей, несмотря на это, следующее делает это предположение.

CREATE TABLE #XMLTempTable(
   ID INT  NOT NULL IDENTITY PRIMARY KEY
  ,DataName  VARCHAR(20) NOT NULL
  ,DataValue VARCHAR(20) NOT NULL
);
INSERT INTO #XMLTempTable(DataName,DataValue) VALUES ('blahblah','blah-1');
INSERT INTO #XMLTempTable(DataName,DataValue) VALUES ('userid','user-1');
INSERT INTO #XMLTempTable(DataName,DataValue) VALUES ('value','value-1');
INSERT INTO #XMLTempTable(DataName,DataValue) VALUES ('blahblah','blah-2');
INSERT INTO #XMLTempTable(DataName,DataValue) VALUES ('userid','user-2');
INSERT INTO #XMLTempTable(DataName,DataValue) VALUES ('value','value-2');
GO
6 rows affected
SELECT 
  id
, blahblah = CASE WHEN  DataName = 'blahblah' THEN datavalue END
, userid = CASE WHEN  DataName = 'userid' THEN DataValue END
, value = CASE WHEN  DataName = 'value' THEN DataValue END
FROM #XMLTempTable
WHERE DataName in ('blahblah', 'userid', 'value')
GO
id | blahblah | userid | value  
-: | :------- | :----- | :------
 1 | blah-1   | <em>null</em>   | <em>null</em>   
 2 | <em>null</em>     | user-1 | <em>null</em>   
 3 | <em>null</em>     | <em>null</em>   | value-1
 4 | blah-2   | <em>null</em>   | <em>null</em>   
 5 | <em>null</em>     | user-2 | <em>null</em>   
 6 | <em>null</em>     | <em>null</em>   | value-2
SELECT 
  (id + 2) / 3 as rowno
, max(CASE WHEN  DataName = 'blahblah' THEN datavalue END) as blahblah
, max(CASE WHEN  DataName = 'userid' THEN DataValue END) as userid
, max(CASE WHEN  DataName = 'value' THEN DataValue END) as datavalue
FROM #XMLTempTable
WHERE DataName in ('blahblah', 'userid', 'value')
GROUP BY
  (id + 2) / 3
GO
rowno | blahblah | userid | datavalue
----: | :------- | :----- | :--------
    1 | blah-1   | user-1 | value-1  
    2 | blah-2   | user-2 | value-2  

дБ <> скрипка здесь

2 голосов
/ 22 февраля 2020

Вы можете достичь этого, используя CASE WHEN .. END

SELECT @blahblah = CASE WHEN  DataName = 'blahblah' THEN IsNull(DataValue,0) ELSE 0 END, 
       @userid = CASE WHEN  DataName = 'userid' THEN IsNull(DataValue,0) ELSE 0 END, 
       @value = CASE WHEN  DataName = 'value' THEN IsNull(DataValue,0) ELSE 0 END
FROM #XMLTempTable
WHERE DataName in ('blahblah', 'userid', 'value')
1 голос
/ 22 февраля 2020

Если у вас есть права на создание функций, вы можете также рассмотреть возможность реализации логики c таким образом, чтобы сделать код непротиворечивым, повторно используемым и совместно используемым. Этот подход удобен для аналитиков данных или администраторов баз данных, которым необходимо часто выполнять обычную логику очистки данных.

Набор тестовых данных

use [testdb];
if OBJECT_ID('testdb..test') is not null
    drop table testdb..test;

create table test (
    DataName varchar(50),
    DataValue varchar(50),
);

insert into test (DataName, DataValue)
values ('name1', NULL),('name2', NULL),('name3', NULL);

select * from test;
GO

Положите свои логи c в многократно используемую функцию

if OBJECT_ID('testdb.dbo.myfunc', 'FN') is not null
    drop function myfunc;
GO

CREATE FUNCTION dbo.myfunc(@param varchar(100))  
RETURNS varchar(100)
AS
BEGIN  
    -- implement your logic here
    declare @ret varchar(max);

    if @param = 'name1'
        set @ret = @param + '_logic1';
    else if @param = 'name2'
        set @ret = @param + '_logic2';
    else if @param = 'name3'
        set @ret = @param + '_logic3';

    return @ret;
END
GO

Выполнить

update A
    set A.DataValue = dbo.myfunc(A.DataName)
    from test as A;

select * from test;
-- DataName  DataValue
-- name1     name1_logic1
-- name2     name2_logic2
-- name3     name3_logic3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...