#sql #tsql #variables #datatables
#sql #tsql #переменные #таблицы данных
Вопрос:
У меня есть таблица с именами и некоторыми значениями. Я хочу передать значения, связанные с именами, в другую таблицу, чтобы предварительно заполнить список значений. Я не уверен, что лучший способ подойти к этому — создать функцию или процедуру.
Ниже приведен запрос, который у меня есть сейчас, где я должен УСТАНОВИТЬ переменные вручную. Но вместо того, чтобы делать это вручную, я хотел бы передать значения из другой таблицы в эту. Как мне это сделать?
Например, у меня есть таблица с именем ABC, и в этой таблице 3 значения
Name|AVG |DEV
A |1.89|.74
B |2.43|1.20
C |.74 |.12
Я хочу передать все значения из этой таблицы в приведенном ниже запросе. Среднее значение в таблице преобразуется в переменную @AVG в приведенном ниже запросе, а значение DEV в таблице — в таблицу @deviation ниже.
Результаты могут быть помещены в новую таблицу или в запрос.
DECLARE @avg DECIMAL(4,1) = 1.89 --this would be row 1 (value A) avg
DECLARE @deviation DECIMAL(4,1) = 0.74 --this would be row 1 (value A) DEV
DECLARE @startnum DECIMAL(4,1)= @Avg - (@deviation * 3)
DECLARE @endnum DECIMAL(4,1)= @Avg (@deviation * 3)
;
WITH gen AS (
SELECT CAST(@startnum AS decimal(4,1)) AS Mulitiple
UNION ALL
SELECT CAST(Mulitiple .1 AS decimal(4,1)) FROM gen WHERE Mulitiple .1<=@endnum
)
SELECT A.Mulitiple , CAST(((A.Mulitiple-@avg)/@deviation) AS DECImAL(4,2)) AS ZScore
,Z.Y AS Area
FROM gen AS A
LEFT JOIN STAT..ZScore AS Z ON CAST(((A.Mulitiple-@avg)/@deviation) AS DECImAL(4,2)) = CAST(Z.Zscore AS decimal(4,2))
--WHERE Z.Y IS NOT NULL
option (maxrecursion 10000)
Комментарии:
1. Я немного потерялся. В таблице три строки с тремя «средними» значениями. Что вы хотите в переменной?
2. Пожалуйста, прочтите это для получения нескольких советов по улучшению вашего вопроса.
3. Вместо рекурсивного CTE строки могут генерироваться более эффективно с использованием «функции чисел» или функции подсчета , и запрос может быть проще
4. Извините, я написал комментарий не полностью. Функция tally напрямую не генерирует zscores. Он генерирует последовательность чисел в виде строк (fn.N), а затем используется для вычисления zscores
5. @SteveC это сработало прекрасно, большое вам спасибо!
Ответ №1:
Этот подход использует функцию подсчета с именем dbo.fnNumbers для генерации диапазона zscores.
dbo.fnNumbers
create function [dbo].[fnNumbers](
@zero_or_one bit,
@n bigint)
returns table with schemabinding as return
with n(n) as (select null from (values (1),(2),(3),(4)) n(n))
select 0 n where @zero_or_one = 0
union all
select top(@n) row_number() over(order by (select null)) n
from n na, n nb, n nc, n nd, n ne, n nf, n ng, n nh,
n ni, n nj, n nk, n nl, n nm, n np, n nq, n nr;
Запрос
drop table if exists #abc;
go
create table #abc(
[name] varchar(2),
[avg] decimal(4,1),
[dev] decimal(4,1));
insert #abc([name], [avg], [dev]) values
('a', 1.89, .74),
('b', 2.43, 1.20),
('c', 0.74, .12);
select a.[name], gen.multiple, gen_z.zscore, z.y as area
from #abc a
cross apply dbo.fnNumbers(1, cast(2*(a.dev*3) 0.1 as decimal(4,1))*10) fn
cross apply (values (cast((a.[avg]-(a.dev*3) (fn.N-1)*0.1) as decimal(4,1)))) gen(multiple)
cross apply (values (cast(((gen.multiple-a.[avg])/a.dev) AS decimal(4,2)))) gen_z(zscore)
left join stat..zscore z on gen_z.zscore=cast(z.zscore as decimal(4,2))
order by a.[name], gen.multiple;
Ответ №2:
Если я правильно понимаю, вы можете просто использовать JOIN
. В этом случае вы можете ввести таблицу с помощью CROSS JOIN
:
SELECT ABC.*, A.Mulitiple ,
CAST(((A.Mulitiple - ABC.avg) / ABC.dev) AS DECImAL(4, 2)) AS ZScore
,Z.Y AS Area
FROM ABC CROSS JOIN
gen a LEFT JOIN
STAT..ZScore Z
ON CAST(((A.Mulitiple - abc.avg)/ abc.dev) AS DECIMAL(4,2)) = CAST(Z.Zscore AS decimal(4,2))
--WHERE Z.Y IS NOT NULL
Вы можете избежать использования формулы дважды, используя:
SELECT ABC.*, A.Mulitiple, v.ZScore, Z.Y AS Area
FROM ABC CROSS JOIN
gen a CROSS APPLY
(VALUES (CAST((A.Mulitiple - ABC.avg) / ABC.dev AS DECImAL(4, 2))
) v(Zscore) LEFT JOIN
STAT..ZScore Z
ON v.ZScore = CAST(Z.Zscore AS decimal(4,2))
--WHERE Z.Y IS NOT NULL
Комментарии:
1. Приведенный ниже запрос генерирует числа, чтобы я мог отображать точки. Эти числа из приведенного ниже запроса основаны на avg и dev из первой строки в ABC, во второй строке avg и DEV будут иметь совершенно разные результаты запроса. Таким образом, количество строк из приведенного ниже запроса будет отличаться каждый раз.