T-SQL Group Check - sql

I have three tables - Table_1, Table_2 and Table_3. Here's what each looks like:
Table_1
ID | TicketID | Rule
---------------------------
1 | 101 | NULL
Table_2
TicketID | Location
---------------------------
101 | A
101 | B
Table_3
Location | Rule
--------------------
A | R1
B | R1
A | R2
B | R2
C | R2
My goal is to populate the Rule column in Table_1 (which should be a select distinct of the Rule column in Table_3). The process should be:
Take the TicketID from Table_1. Join Table_1 to Table_2 on TicketID and get the Locations associated with that ticket.
Look up Table_3 and check what Rule needs to be applied. The check needs to be at the group level. For instance, in this example, Ticket 101 has locations A,B. Table_3 has A,B against Rule R1 but also has A,B,C against Rule R2. The correct rule should be R1 as Ticket 101 has no allocation for location C. Hope this make sense. What would be the easiest way of achieving this? Thanks in advance!

Please try the below code. Its working fine in SQL server 2012.
DECLARE #table_1 TABLE
(ID int, TicketID int, [Rule] Varchar(10))
DECLARE #table_2 TABLE
(TicketID int, Location Varchar(10))
DECLARE #table_3 TABLE
(Location Varchar(10),[Rule] Varchar(10))
INSERT #table_1
(ID,TicketID,[Rule])
VALUES
(1,101,NULL)
INSERT #table_2
(TicketID,Location)
VALUES
(101,'A'),
(101,'B')
INSERT #table_3
(Location,[Rule])
VALUES
('A','R1'),
('B','R1'),
('A','R2'),
('B','R2'),
('C','R2')
SELECT DISTINCT [RULE] FROM #table_3 t3 WHERE t3.Location IN
(SELECT t2.Location FROM #table_2 t2 INNER JOIN #table_1 t1 ON t1.TicketID = t2.TicketID)
AND [RULE] NOT IN
(SELECT t.[RULE] FROM #table_3 t WHERE t.Location NOT IN
(SELECT t2.Location FROM #table_2 t2 INNER JOIN #table_1 t1 ON t1.TicketID = t2.TicketID))

TRY THIS..
SELECT t1.TicketID
,t2.[Rule]
FROM (SELECT DISTINCT t2.TicketID,[Rule]
FROM #table_3 t3 INNER JOIN
#table_2 t2 ON t2.Location = t3.Location) t2
INNER JOIN #table_1 t1 ON t2.TicketID = t1.TicketID
Use this select statement with the above declared table variable

--http://stackoverflow.com/questions/37344006/t-sql-group-check
set nocount on
drop table #temp
DECLARE #table_1 TABLE
(ID int, TicketID int, [Rule] Varchar(10))
DECLARE #table_2 TABLE
(TicketID int, Location Varchar(10),obs int)
DECLARE #table_3 TABLE
(Location Varchar(10),[Rule] Varchar(10), obs int)
INSERT #table_1
(ID,TicketID,[Rule])
VALUES
(1,101,NULL)
INSERT #table_2
(TicketID,Location)
VALUES
(101,'A'),
(101,'B'),
--(101,'C')
(102,'A'),
(102,'B'),
(102,'C'),
(102,'S')
INSERT #table_3
(Location,[Rule])
VALUES
('A','R1'),
('B','R1'),
('A','R2'),
('B','R2'),
('C','R2'),
('S','R2')
declare #table_4 table (src varchar(2), id varchar(3), obs int)
insert into #table_4
select 't2', [ticketid], count(*) from #table_2 group by [ticketid]
Insert into #table_4
select 't3',[rule], count(*) from #table_3 group by [rule]
update #table_2
set obs = t4.obs
from #table_2 t2
join #table_4 t4 on t4.id = t2.ticketid
where t4.src = 't2'
update #table_3
set obs = t4.obs
from #table_3 t3
join #table_4 t4 on rtrim(t4.id) = rtrim(t3.[rule])
where t4.src = 't3'
select t2.ticketid,t2.location as t2location,t2.obs as t2obs,t3.location as t3location,t3.[Rule],t3.obs as t3obs
into #temp
from #table_2 t2
full join #table_3 t3 on t3.location = t2.location
delete #temp
where [rule] in (select [rule] from #temp where ticketid is null)
--select t.*
--from #temp t
select distinct ticketid,[rule]
from #temp
where t2location = t3location and t2obs = t3obs

Try this code :
SELECT DISTINCT [RULE] FROM Table_3 t3 WHERE t3.Location IN
(SELECT t2.Location FROM Table_2 t2 INNER JOIN Table_1 t1 ON t1.TicketID = t2.TicketID)
AND [RULE] NOT IN
(SELECT t.[RULE] FROM Table_3 t WHERE t.Location NOT IN
(SELECT t2.Location FROM Table_2 t2 INNER JOIN Table_1 t1 ON t1.TicketID = t2.TicketID))

Related

sql for breaking one record into 2 records

I have 2 tables with data as below-
table 1-
id name id_start_date
---------------------
345 Fiamma 1/01/1900
Table 2-
Change_Date Old_id New_id Users
-------------------------------
15/06/2017 123 345 abc#xyz.com
I'm looking for data as below-
id product_name start_date end_date
-----------------------------------
123 Fiamma 1/01/1900 15/06/2017
345 Fiamma 15/06/2017 31/12/2099
Basically I want to break the table 2 data into 2 records one with old id and the start and end dates for that id and the other with the new id with start and end dates.
Cheers
select t2.old_id as id, t1.name as product_name, t1.start_date, t2.change_date as end_date
from table1 t1
INNER JOIN table2 t2 ON t1.id = t2.new_id
UNION
select t1.id as id, t1.name as product_name, t2.change_date, "" as end_date
from table1 t1
INNER JOIN table2 t2 ON t1.id = t2.new_id
here is a test that you can run :
create table #table1
(
id int,
name varchar(50),
start_date datetime
)
GO
create table #table2
(
change_date datetime,
Old_id int,
New_id int,
users varchar(50)
)
GO
insert into #table1
values (345,'Fiamma','01/01/1900')
insert into #table2
values ('15/06/2017',123,345,'abc#xyz.com')
select * from #table1
select * from #table2
select t2.old_id as id, t1.name as product_name, t1.start_date as start_date, t2.change_date as end_date
from #table1 t1
INNER JOIN #table2 t2 ON t1.id = t2.new_id
UNION
select t1.id as id, t1.name as product_name, t2.change_date as start_date , DATEADD(YEAR,+10,GETDATE()) as end_date
from #table1 t1
INNER JOIN #table2 t2 ON t1.id = t2.new_id
drop table #table1
drop table #table2

Skip all rows if one row id is present in another table

I have three tables with this relation:
T1.journo = T2.journo
T2.recid = T3.spid
T1
ticketno journo
1 A1
2 A2
T2
journo recid
A1 1
A1 2
A1 3
A2 4
A2 5
A2 6
T3
spid
2
I want only those entries of T1 where T2.recid is not present in T3.spid.
Below query will just omit the 2nd row of T2. But I want all the rows of T2 with journo=A1 omitted because one of the recid of A1 is present in T3.
select T1.* from T1 join T2 on T1.journo = T2.journo
where T2.recid not in (select spid from T3)
Desired Output:
ticketno journo
2 A2
Any tips?
To me, this sounds like not exists:
select t1.*
from t1
where not exists (select 1
from t2 join
t3
on t2.recid = t3.spid
where t2.journo = t1.journo
);
Should be able to use not in with a sub query.
declare #t1 table (ticketno int identity(1,1), journo varchar(2))
declare #t2 table (journo varchar(2), recid int identity(1,1))
declare #t3 table (spid int)
insert into #t1
values
('A1'),
('A2')
insert into #t2
values
('A1'),
('A1'),
('A1'),
('A2'),
('A2'),
('A2')
insert into #t3
values
(2)
select T1.* , T2.*
from #t1 T1
inner join #t2 T2 on T1.journo = T2.journo
where T2.journo not in (select t22.journo from #t2 t22 where t22.recid in (select * from #t3))
Or, not exists correlated
where not exists(select t22.journo from #t2 t22 where t22.recid in (select * from #t3) and t22.journo = T2.journo)
Join T2 on T3 with left a left join. group on the t1 variables then do a having check of COUNT(t3.spid) = 0.
Any nulls shouldn't be counted and so zero on the count is what your looking for.
SELECT t1.*
FROM #t1 t1
JOIN #t2 t2 ON t2.journo = t1.journo
LEFT JOIN #t3 t3 ON t3.spid = t2.recid
GROUP BY t1.ticketno, t1.journo
HAVING COUNT(t3.spid) = 0
SQL, the ugly but necessary part of our lives:
SELECT * FROM T1
INNER JOIN
(SELECT a1.journo
, SUM(spid_present) AS 'total_spids'
FROM
(SELECT T2.journo
, T2.ticketno
, CASE
WHEN t3.spid IS NOT NULL
THEN 1
ELSE 0
END AS 'spid_present'
FROM T2
LEFT JOIN T3
ON T2.recid = T3.spid) a1
GROUP BY a1.journo) a2
ON T1.journo = a2.journo
AND a2.total_spids = 0}
Using EXCEPT:
create table t1 (ticketno int, journo char(2))
insert into t1 values (1, 'A1'), (2, 'A2')
create table t2 (journo char(2), recid int)
insert into t2 values ('A1', 1), ('A1', 2), ('A1', 3), ('A2', 4), ('A2', 5), ('A2', 6)
create table t3 ([SPID] int)
insert into t3 values (2)
select t1.* from t1
except
select t1.*
from t1
inner join t2 on t2.journo = t1.journo
inner join t3 on t2.recid = t3.[SPID]
You can try the below SQL query.
select T.* from T1 , T2 a where T1.journo = a.journo and a.recid not exists (select 1 from T3, T2 where T2.recid= T3.spid and T2.recid =a.reci);
By my understanding, simple join
select t1.* from #t1 t1
join #t2 t2
on t1.journo <> t2.journo
join #t3 t3
on t2.recid = t3.spid

Update table using like operator

I have 2 tables
table 1
Diagnosis GroupID
155.0 - blaaaaaa GAS
table 2
Code GroupID
155.0
155.0
155.0
155.0
I did try to update GroupID of second table from first
update Table2 set GroupID= GroupID from table 1 where Diagnosis like '%'+Code+'%'
but its not working
Your current syntax for an update join is slightly off. Try using this instead:
UPDATE t2
SET GroupID = t1.GroupID
FROM Table2 t2
INNER JOIN Table1 t1
ON t1.Diagnosis LIKE '%' + t2.Code + '%'
You can use the following code:
UPDATE
Tb2 SET Tb2.GroupId = Tb1.GroupId
FROM table1 as Tb1 INNER JOIN table2 as Tb2
ON Tb1.Diagnosis LIKE '%'+Tb2.Code+'%';
This would help, http://rextester.com/NILBI39557
CREATE TABLE Table1
(
Diagnosis VARCHAR(255)
,GROUPID VARCHAR(255)
);
Insert Into Table1 Values('155.0 - blaaaaaa','GAS');
CREATE TABLE Table2
(
Code VARCHAR(255)
,GROUPID VARCHAR(255)
);
Insert Into Table2 VALUES ('155.0', NULL);
Insert Into Table2 VALUES ('155.0', NULL);
Insert Into Table2 VALUES ('155.0', NULL);
Insert Into Table2 VALUES ('155.0', NULL);
SELECT * FROM Table2;
UPDATE T2
SET T2.GroupId = T1.GroupId
FROM Table1 as T1 INNER JOIN Table2 as T2
ON T1.Diagnosis LIKE '%'+T2.Code+'%';
SELECT * FROM Table2;

SQL Join query to show records if exists in master table or not

Table1
id name color
1,'a','red'
2,'a','blue'
3,'b','red'
4,'c','red'
5,'d','red'
6,'a','green'
declare #t1 table (id int, name varchar(10),color varchar(5))
insert into #t1 values(1,'a','red')
insert into #t1 values(2,'a','blue')
insert into #t1 values(3,'b','red')
insert into #t1 values(4,'c','red')
insert into #t1 values(5,'d','red')
table t2 (master table )
color
red
blue
green
declare #t2 table (color varchar(5))
insert into #t2 values ('red')
insert into #t2 values ('blue')
insert into #t2 values ('green')
The output will be
'a','red'
'a','blue'
'a','green'
We need to retrieve the name from table 1 what are all having all the t2 color...
You can get the names in t1 that match all master colors using group by, having, and join:
select t1.name
from t1 join
t2
on t1.color = t2.color
group by t1.name
having count(distinct t1.color) = (select count(*) from t2);
This returns the names. If you want the detailed rows, then use this as a subquery or CTE and join t1 back to these results.
And to get the detailed rows:
with n as (
select t1.name
from t1 join
t2
on t1.color = t2.color
group by t1.name
having count(distinct t1.color) = (select count(*) from t2)
)
select t1.*
from t1 join
n
on t1.name = n.name;

left outer join in t-sql

I have the following two tables. I am using SQL Server 2008 R2
Create table #tmp1 (
a char(1)
)
Create table #tmp2 (
id int,
a char(1),
val int
)
insert #tmp1 values ('A')
insert #tmp1 values ('B')
insert #tmp1 values ('C')
insert #tmp2 values (1, 'A', 10)
insert #tmp2 values (1, 'B', 20)
insert #tmp2 values (2, 'A', 30)
insert #tmp2 values (2, 'C', 40)
select * from #tmp1 t1 left outer join #tmp2 t2 on t1.a = t2.a
order by t2.id
This returns the result set
A 1 A 10
B 1 B 20
C 2 C 40
A 2 A 30
I would like to have the following result set
A 1 A 10
B 1 B 20
C 1 null null
A 2 A 30
B 2 null null
C 2 C 40
Right now i am acheiving this by creating a new table with a cross join like this and then doing a outer join
select * into #tmp3 from #tmp1 cross join (select distinct ID from #tmp2) t
select * from #tmp3 t1 left outer join #tmp2 t2 on t1.a = t2.a and t1.id = t2.id
Is there a better way to do this ?
Thanks
To get what you want, you need a "driving" table. That is, you want a complete list of all combinations, and then to join to the other tables to get the matches. Here is one way:
select t1.a, t2.*
from (select t1.a as a, t2.id as id
from (select distinct a from #tmp1 t1) t1
cross join
(select distinct id from #tmp2 t2) t2
) driving left outer join
#tmp1 t1
on t1.a = driving.a left outer join
#tmp2 t2
on t2.id = driving.id and
t2.a = driving.a
order by t2.id
What you are looking for is a cartesian product of the values in #tbl1 and the values in the id column in #tbl2. Because the values in #tbl2.id are not unique it might be a better design to have an additional table with a row for each #tbl2.id value. Then you can use this solution:
Create table #tmp1 (
a char(1)
)
Create table #tmp2 (
id int,
a char(1),
val int
)
Create table #tmp3 (
id int
)
insert #tmp1 values ('A')
insert #tmp1 values ('B')
insert #tmp1 values ('C')
insert #tmp3 values (1)
insert #tmp3 values (2)
insert #tmp2 values (1, 'A', 10)
insert #tmp2 values (1, 'B', 20)
insert #tmp2 values (2, 'A', 30)
insert #tmp2 values (2, 'C', 40)
SELECT t3.id,t1.a,t2.val
FROM #tmp1 AS t1
CROSS JOIN #tmp3 AS t3
LEFT OUTER JOIN #tmp2 AS t2
ON t1.a = t2.a AND t3.id = t2.id
ORDER BY t3.id, t1.a;
If that is not an option use this instead:
SELECT t3.id,t1.a,t2.val
FROM #tmp1 AS t1
CROSS JOIN (SELECT DISTINCT id FROM #tmp2) AS t3
LEFT OUTER JOIN #tmp2 AS t2
ON t1.a = t2.a AND t3.id = t2.id
ORDER BY t3.id, t1.a;