SQL select from column where column equals table variable? - sql

I'm a serious SQL noob so any help is appreciated. I'm having a hard time even explaining what I'm trying to do so I'll lay out what I have so far:
DECLARE #UserIDInt table (ID int);
INSERT into #UserIDInt
SELECT UserId
FROM [LcsCDR].[dbo].[Users]
WHERE [LcsCDR].[dbo].[Users].[UserUri] LIKE '%example';
SELECT *
FROM [LcsCDR].[dbo].[SessionDetails]
WHERE [LcsCDR].[dbo].[SessionDetails].[User1Id] = #UserIDInt;
"DECLARE #UserIDInt table (ID int);"
This creates my variable with a column called "ID"
INSERT into #UserIDInt
SELECT UserId
FROM [LcsCDR].[dbo].[Users]
WHERE [LcsCDR].[dbo].[Users].[UserUri] LIKE '%example';
This adds numeric values into the ID column based on whether or not the WHERE statement matched
SELECT *
FROM [LcsCDR].[dbo].[SessionDetails]
WHERE [LcsCDR].[dbo].[SessionDetails].[User1Id] = #UserIDInt;
This is where I am lost. I am trying to return all rows from [LcsCDR].[dbo].[SessionDetails] if the column [LcsCDR].[dbo].[SessionDetails].[User1Id] matches anything in my variable. The problem (I think) I'm having is that SQL can't look within the variable's column to find multiple values. Basically, the ID column in my variable #UserIDInt will contain a bunch of numeric values.
How do I perform the final SELECT statement and have SQL return all results if [LcsCDR].[dbo].[SessionDetails].[User1Id] matches anything within my #UserIDInt.ID column?
I am using SQL Server 2014.
Apologies if I explained it badly. Not sure how else to ask the question :)

using inner join:
select sd.*
from [lcscdr].[dbo].[sessiondetails] sd
inner join #useridint i
on i.id = sd.user1id;
or using exists():
select sd.*
from [lcscdr].[dbo].[sessiondetails] sd
where exists (
select 1
from #useridint i
where i.id = sd.user1id
);
or using in():
select sd.*
from [lcscdr].[dbo].[sessiondetails] sd
where sd.user1id in (
select id
from #useridint i
);
rextester demo: http://rextester.com/UVCB28056

Use EXISTS:
SELECT T1.*
FROM [lcscdr].[dbo].[sessiondetails] T1 WHERE EXISTS (
SELECT 1
FROM #useridint T2
WHERE T2.id = T1.user1id
);

Related

Pass values as parameter from select query

I want to pass values from output of select query to another query. Basically both queries will be part of a stored procedure. e.g.
select Id, RelId
from tables
There will be multiple rows returned by above query and I want to pass them to the following query
select name
from table2
where Id = #Id and MgId = #RelId
Please suggest
You cannot pass multiple values in SQL.
But maybe you can just join your 2 tables, that would be far more efficient.
Not knowing your table schemes I suggest something like this. You might have to adapt this to your actual table schemas off course
select name
from table2 t2
inner join tables t on t2.Id = t.Id
and t2.MgId = t.RelId
EDIT
As Gordon mentioned in his answer, this approach can show double rows in your result.
If you don't want that than here are 2 ways of getting rid of the doubles
select distinct name
from ...
or by grouping by adding this at the end of the statement
group by name
Though this will work, avoiding the doubles like in Gordon's answer is better
I would suggest using exists:
select t2.name
from table2 t2
where exists (select 1
from tables t
where t2.Id = t.Id and t2.MgId = t.RelId
);
The difference between exists and join is that this will not generate duplicates, if there are multiple matches between the tables.
Or...
SELECT *
INTO #Table1
FROM ...
SELECT *
INTO #Table2
FROM ...
SELECT *
FROM #Table1 T1
JOIN #Table2 T2
DROP TABLE #Table1, #Table2

Dynamically storing values in SQL table

I'm trying to dynamically create a variable or table in SQL which will store distinct values as a result for another sql query.
declare sample_table table
( values varchar(100))
insert into #sample_table values (select t1.value from my_tablw as t1 group by t1.value);
Supposing the distinct values in column value can change from table query to another table query, I want to store the result of this query in a user defined variable/table which can be used later in another query.
Depending on your definition of can be used later you can use a local temp table or table variable.... you just need to change the syntax a bit to not use the values since you are inserting from the results of a query. I also used DISTINCT below which is clearer than the GROUP BY without an aggregate function.
declare sample_table table ([values] varchar(100))
insert into #sample_table
select distinct t1.value
from my_tablw as t1
--one way to use it
select *
from newTable
where columnVal in (select * from #sample_table)
--another way to use it
select at.*
from anotherTable at
inner join #sample_table t on
t.column = at.column
--and another way...
select f.*
from finalTable f
where exists (select * from #sample_table t where t.column = f.column)
If you need this to be used outside the scope of your current batch, you'll need to use a persisted table or global temporary table.

SQL Update Multiple Rows with Count from another Table

Suppose I have two tables. One table, tbl1, is "long" and non-aggregated. The structure is as follows:
Software_Name:
Word
PowerPoint
PowerPoint
Excel
Word
PowerPoint
In a second Table, tbl2, I want to summarize the data from the first table, namely the count of Software. The second Table will have a structure like:
Software_Name: Count:
Word 2
PowerPoint 3
Excel 1
I have tried:
update tbl2
set count =
(select count(software_name)
from tbl1
group by software_name
where tbl1.software_name = tbl2.software_name)
from tbl1
I get a result inserted into the proper column, but it is not the proper value. It is the sum of all values, in this case 5. I have included the where clause because in my tbl1 I have many more software_names than am interested in counting in tbl2.
UPDATE
I am using Teradata Aster for this project. I have been looking at the Aster documentation for the UPDATE command and came across this:
UPDATE [ ONLY ] table
SET column = expression [, ...]
[ FROM fromlist ]
[ WHERE condition | WHERE CURRENT OF cursor_name ];
In reading about the fromlist, I came across this bit of information:
Note that the target table must not appear in the fromlist unless you intend a
self-join (in which case it must appear with an alias in the fromlist).
You want a correlated subquery:
update tbl2
set count = (select count(*) from tbl1 where tbl1.software_name = tbl2.software_name);
Not sure what DBMS you're using but in SQL Server I would recommend a CROSS APPLY with example below...
update t2
set t2.[Count] = t1.[Count]
from t2
cross apply (
select count(*) AS [Count]
from t1
where t1.Software_name = t2.Software_name
) AS t1
You can read more about the APPLY operator here: https://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/
You can try using the CTE as below:
DECLARE #TABLE1 AS TABLE (Software_Name VARCHAR(100))
INSERT INTO #TABLE1
SELECT 'Word'
UNION ALL
SELECT 'PowerPoint'
UNION ALL
SELECT 'PowerPoint'
UNION ALL
SELECT 'Excel'
UNION ALL
SELECT 'Word'
UNION ALL
SELECT 'PowerPoint'
DECLARE #TABLE2 AS TABLE (Software_Name VARCHAR(100),Cnt INT)
INSERT INTO #TABLE2 (Software_Name)
SELECT DISTINCT Software_Name FROM #TABLE1
;WITH CTE AS
(
SELECT
COUNT(T1.Software_Name) AS Cnt
,T1.Software_Name
FROM #TABLE2 T2
INNER JOIN #TABLE1 T1 ON T1.Software_Name = T2.Software_Name
GROUP BY
T1.Software_Name
)
UPDATE T2
SET
T2.Cnt = C.Cnt
FROM #TABLE2 T2
INNER JOIN CTE C ON C.Software_Name = T2.Software_Name
SELECT * FROM #TABLE2
NOTE: I am assuming you are using SQL Server. Also i am posting it as an answer as i dont have desired reputation to comment.
hope it helps!

SQL update statement with different table in from clause

Out of accident I noticed that the following query is actually valid:
UPDATE bikes
SET price = NULL
FROM inserted
WHERE inserted.owner_id = 123456
This is part of a trigger where someone forgot to join the original table to the inserted table. The result is that when the trigger is executed, all prices are set to NULL.
The correct SQL statement is this:
UPDATE bikes
SET price = NULL
FROM inserted
INNER JOIN bikes ON bikes.id=inserted.id
WHERE inserted.owner_id = 123456
How/why is this first statement valid?
Why wouldn't it be valid? SQL Server doesn't know what you're trying to do. It thinks you want to update all of the fields where some condition exists on another table. See the last update below.
SETUP
declare #table table
(
id int,
name varchar(10)
)
declare #itable table
(
id int,
name varchar(10)
)
insert into #table (id, name)
select 1,'abc' union
select 2,'def' union
select 3,'ghi' union
select 4,'jkl' union
select 5,'mno' union
select 6,'pqr'
insert into #itable (id, name)
select 1,'abc' union
select 2,'def' union
select 3,'ghi' union
select 4,'jkl' union
select 5,'mno' union
select 6,'pqr'
All names on #table will change to zzz
update #table
set name = 'zzz'
from #itable i
where i.id = 1
select * from #itable
select * from #table
All names where id = 1 on #table becomes yyy
update #table
set name = 'yyy'
from #itable i
inner join #table t on i.id = t.id
where i.id = 1
select * from #itable
select * from #table
This will NOT update anything
update #table
set name = 'aaa'
from #itable i
where i.id = 133
select * from #itable
select * from #table
The first statement does not work as expected because it is missing the entire INNER JOIN line with the bikes and inserted table. Without that SQL Server will update all rows as all rows will qualify for an update when the inserted.owner_id = 123456.
You can reproduce this outside of the trigger in TSQL like :
update bikes set price =null
from SomeOtherTable
where SomeOtherTable.SomeColumn = 'some_value_that_exists'
This is syntactically valid statement in SQL Server. If the Intention is to update bikes table based on existance of a row in some unrelated table that cant be joined because the 2 tables arent related then this is how you would do it. But that is not your requirement. Hence why it updates all records instead of only those that match the bikes.id In programming terms this is called as a logical bug.
The inner join makes it more restrictive and forces to to update only those rows that match the join condition between the 2 tables (bikes.id=inserted.id comparison )
In Simple terms the from clause is optional..Consider below query..
update table
set id=10
This has one table right after update clause ,sql just updates it..
now consider below query..
update table1
set id=40
from table2..
What do you think SQL does,it updates all the rows same as first query..
unless you refer to another table in from clause and join like below
update t1
set t1.id=40
from
table1 t1
join
table2 t2
on t1.id=t2.id
below is the from clause explanation in update syntax stripped down to show only to relevant parts..
If the object being updated is the same as the object in the FROM clause and there is only one reference to the object in the FROM clause, an object alias may or may not be specified. If the object being updated appears more than one time in the FROM clause, one, and only one, reference to the object must not specify a table alias. All other references to the object in the FROM clause must include an object alias
As long as above rules are valid (as in your case),SQL will happily update table found immediately after update clause

Why can I reference a field from an outer query in SQL

Given theses tables:
create temporary table a(pid integer, cid integer);
create temporary table b(id integer, code varchar);
This works but returns wrong results:
select pid
from a
where cid in (select cid from b where code like 'AE%')
I just had a query like that where I use the wrong field, and it surprised me that that query even works. Doesn't a query like this just return all the rows from table a ?
Do you have any example of a query written like this that would be useful ?
Maybe I'm missing something.
You regulary need fields from the outer query in the where clause of the inner query:
select * from a
where exists ( select 1 from b where id = cid );
or
select * from a
where 'HELLO' in (select code from b where id = cid );
We can also construct examples where the outer fields are (kind of) useful in the select clause:
select * from a
where 1 = any (select id-cid from b where code like 'HE%');
Therefore, access to the fields of the outer query is absolutely necessary.