How to pass a query as a variable - sql-server

DECLARE #SomeVariableTable TABLE (
Field INT
)
INSERT INTO #SomeVariableTable
SELECT st.Field
FROM SomeTable st;
SELECT *
FROM AnotherTable at
WHERE at.SomeField IN #SomeVariableTable
How can I make the above code work?
I have looked at concatenating the entire column into a VARCHAR and while this works for VARCHARs it doesn't work for INTs.

Your code is almost fine except the last SELECT. Change the last SELECT part as below.
SELECT *
FROM AnotherTable at
WHERE at.SomeField IN (select Field from #SomeVariableTable)

This is how you would do what you are trying to do .....
DECLARE #SomeVariableTable TABLE (
Field INT
)
INSERT INTO #SomeVariableTable
SELECT st.Field
FROM SomeTable st;
SELECT *
FROM AnotherTable at
WHERE at.SomeField IN (
SELECT Field
FROM #SomeVariableTable
)
But why would you do this anyway? you could have simply done something like
SELECT *
FROM AnotherTable at
WHERE at.SomeField IN (
SELECT Field
FROM SomeTable
)

Related

Capturing all the columns in a select statement except one from a table

Is there any way to select all the columns except one in Snowflake like we have in bigquery:
select * except(columnname) from table
2022 update: Snowflake now supports EXCLUDE():
Test with:
with data as (
select 1 col_a, 2 col_b, 3 col_c, 4 col_d
)
select *, col_a as id
exclude (col_c, col_b, col_a)
from data
https://twitter.com/felipehoffa/status/1593311749100294144
Previous answer:
In lieu of the EXCEPT syntax, I wrote a stored procedure that can give you the list of columns to SELECT for:
create or replace procedure cols_except(table_name varchar, except varchar)
returns varchar
language sql as
begin
describe table identifier(:table_name);
return (
select listagg("name", ', ') cols_except
from table(result_scan(last_query_id()))
where not array_contains("name"::variant, (split(:except, ',')))
);
end;
You can use it to get the columns to select for, after eliminating the values that match the except clause:
call cols_except('snowflake_sample_data.tpch_sf1.nation', 'N_NAME,N_REGIONKEY');
Snowflake supports natively SELECT * EXCLUDE(<col_list>) syntax:
SELECT * EXCLUDE id FROM tab1;
SELECT * EXCLUDE (id, col1) FROM tab1;
For sample data:
CREATE OR REPLACE TABLE tab1(id INT, col1 TEXT, col2 TEXT)
AS
SELECT 1, 'a', 'b';
Output:

Snowflake insert into a table from CTE output results

with
ct2 (emp_name,emp_id) as (
select emp_name,emp_id
from "TEST_1"."PUBLIC"."TEST11"
)
insert into "TEST_1"."PUBLIC"."EMP1"
select emp_name,emp_id
from ct2;
I guess you are looking for the correct syntax to achieve the above.
Try this:
insert into "TEST_1"."PUBLIC"."EMP1"
with ct2 (emp_name,emp_id) as (select emp_name,emp_id from "TEST_1"."PUBLIC"."TEST11")
select emp_name,emp_id from ct2;

Getting a Row Count and keeping the columns with no rows are returned

If I run something like this:
select [agent_name], [agent_department], count(*) as [row_count]
from [table_name]
where [agent_name] IS NOT NULL
group by [agent_name] [agent_department];
Nothing will come back if there are no records to return (i.e. the table is empty).
If I run this
select count(*) as [row_count]
from [table_name]
where [agent_name] IS NOT NULL
I will get a row_count of 0.
Is there a way I can run the first query, and, if there are no records, have it return row_count 0?
This might not be very beautiful, but it should bring back what you want:
I start with a tiny mockup:
DECLARE #mockup TABLE(agent_name varchar(100),agent_department varchar(100));
--The query will read your SELECT within a CTE.
WITH cte AS
(
select [agent_name], [agent_department], count(*) as [row_count]
from #mockup
where [agent_name] IS NOT NULL
group by [agent_name],[agent_department]
)
SELECT agent_name,agent_department,row_count FROM cte
UNION ALL SELECT NULL,NULL,0 WHERE (SELECT COUNT(*) FROM cte)=0;
The result
agent_name agent_department row_count
NULL NULL 0
You see, that the resultset is called as is, while there is a UNION ALL SELECT query, which will deliver only in cases, where the cte has no rows.
Now we insert some data to the table
INSERT INTO #mockup VALUES('blah','blub');
WITH cte AS
(
select [agent_name], [agent_department], count(*) as [row_count]
from #mockup
where [agent_name] IS NOT NULL
group by [agent_name],[agent_department]
)
SELECT agent_name,agent_department,row_count FROM cte
UNION ALL SELECT NULL,NULL,0 WHERE (SELECT COUNT(*) FROM cte)=0;
the new result is now
agent_name agent_department row_count
blah blub 1

Filling the ID column of a table NOT using a cursor

Tables have been created and used without and ID column, but ID column is now needed. (classic)
I heard everything could be done without cursors. I just need every row to contain a different int value so I was looking for some kind of row number function :
How do I use ROW_NUMBER()?
I can't tell exactly how to use it even with these exemples.
UPDATE [TableA]
SET [id] = (select ROW_NUMBER() over (order by id) from [TableA])
Subquery returned more than 1 value.
So... yes of course it return more than one value. Then how to mix both update and row number to get that column filled ?
PS. I don't need a precise order, just unique values. I also wonder if ROW_NUMBER() is appropriate in this situation...
You can use a CTE for the update
Example
Declare #TableA table (ID int,SomeCol varchar(50))
Insert Into #TableA values
(null,'Dog')
,(null,'Cat')
,(null,'Monkey')
;with cte as (
Select *
,RN = Row_Number() over(Order by (Select null))
From #TableA
)
Update cte set ID=RN
Select * from #TableA
Updated Table
ID SomeCol
1 Dog
2 Cat
3 Monkey
You can use a subquery too as
Declare #TableA table (ID int,SomeCol varchar(50))
Insert Into #TableA values
(null,'Dog')
,(null,'Cat')
,(null,'Monkey');
UPDATE T1
SET T1.ID = T2.RN
FROM #TableA T1 JOIN
(
SELECT ROW_NUMBER()OVER(ORDER BY (SELECT 1)) RN,
*
FROM #TableA
) T2
ON T1.SomeCol = T2.SomeCol;
Select * from #TableA

SQL Server union temp tables

I have a piece of SQL that takes a parameter, assesses the contents of the parameter and depending on the contents applies different UDF to the input parameter.
the code goes something like this:
declare #order varchar(50) = 's12345..s12347'
if isnull( CHARINDEX('.',#order),0) >0
begin
select n as order_no into #temp
FROM F_GetAllNBetween(#order)
end
else if ( isnull( CHARINDEX(',',#order),0) >0 )
begin
select [value] as order_no into #temp2
FROM dbo.F_SplitList(#order,',')
end
if OBJECT_ID('tempdb..#temp') is not null
select * from #temp where order_no <>''
if OBJECT_ID('tempdb..#temp2') is not null
select * from #temp2 where order_no <>''
what I want to do is, get the output from the above union into another temp table and use it in the where clause of the rest of the code.
I cannot use union as it errors saying a select is expected.
I cannot use cte as I cannot use the check to see if the temp tables are empty
I cannot ignore checking for empty temp tables else it errors saying object does not exist ( if statement only creates one of the two temp tables)
I cannot figure out how to get the output to a different temp table. Any ideas suggestions or better way of doing the same please?
As mentioned in my comment, you can simplify your current code to achieve what you want with a UNION and WHERE clauses to replace the IF statements. e.g.
SELECT order_no
--INTO #someTempTable -- if needed
FROM (
SELECT order_no = n
FROM dbo.F_GetAllNBetween(#order)
WHERE CHARINDEX('.', #order) > 0
UNION ALL
SELECT value
FROM dbo.F_SplitList(#order,',')
WHERE CHARINDEX(',', #order) > 0
) AS T
WHERE order_no <> '';

Resources