Insert into one table from another two table - sql

I have 3 tables
declare #approval_request table(req_id int, file_id int, req_type varchar(100))
insert into #approval_request
values (1, 1001, 'bulk'),
(2, 1002, 'demo'),
(3, 1003, 'bulk'),
(4, 1004, 'test');
declare #bulk_account table (file_id int, account varchar(50));
insert into #bulk_account
values (1001, '501'), (1002, '401'),
(1001, '502'), (1002, '402'),
(1001, '503'), (1002, '403');
I want to get all file_id from approval_request table where type='bulk' then
all accounts for corresponding file_id from second table(bulk_account ) and insert into third table as below.
declare #approval_bulk_account table
(
req_id int,
account varchar(50)
);
so the new table data will be
(req_id, account)
1 501
1 502
1 503

insert into #approval_bulk_account
select a.req_id,b.account
from #approval_request a
inner join #bulk_account b on a.file_id = b.file_id
and a.req_type = 'bulk';

Try to insert into the third table with inner join on first 2 tables, something like this
insert into approval_bulk_account
(req_id,account)
select a.req_id , b.account
from approval_request a inner join bulk_account b
on a.file_id =b.file_id
where a.req_type ='bulk'

Related

Select parent and child records while search child record

I have two tables 'Family' and 'FamilyLink'. If I search the 'Family', I need the parent entries also.
Family:
Id Name Type
1 A 1
2 A1 2
3 AAA 3
4 B 1
5 B1 2
6 BBB 3
0 0 0
FamilyLink:
Id parentId
1 0
2 1
3 2
4 0
5 4
6 5
If I search 'AAA' I want results like below
Id Parent Id Name
1:0 0 A
2:1 1:0 A1
3:2 2:1 AAA
If I search 'BBB' I want results like below
Id Parent Id Name
4:0 0 B
5:4 4:0 B1
6:5 5:4 BBB
If nothing in search the results shown like below:
Id Parent Id Name
1:0 0 A
2:1 1:0 A1
3:2 2:1 AAA
4:0 0 B
5:4 4:0 B1
6:5 5:4 BBB
I tried like below query
SELECT DISTINCT F1.ID, FL1.PARENTID, F1.NAME
FROM FAMILY F1 INNER JOIN FAMILYLINK FL1 ON F1.ID= F1.ID
INNER JOIN FAMILY F2 ON F2.ID = FL1.PARENTID
INNER JOIN FAMILYLINK FL2 ON FL2.ID = F2.ID WHERE F1.NAME
LIKE '%AAA%'
Sample table create:
Create table Family (Id int, Name varchar(50), Type int)
insert into family values (0, 'O', 0)
insert into family values (1, 'A', 1)
insert into family values (2, 'A1', 2)
insert into family values (3, 'AAA', 3)
insert into family values (4, 'B', 1)
insert into family values (5, 'B1', 2)
insert into family values (6, 'BBB', 3)
Create table FamilyLink (Id int, parentId int)
insert into FamilyLink values (1, 0)
insert into FamilyLink values (2, 1)
insert into FamilyLink values (3, 2)
insert into FamilyLink values (4, 0)
insert into FamilyLink values (5, 4)
insert into FamilyLink values (6, 5)
Not getting the expected result.
please help.
thanks
I feel like the tables are a bit wierd?
If you want BBB's parent to be B1, shouldn't the parentid of id 6 in familylinks be 5 instead of 2? Because when I look at your sample tables it looks like BBB's parent is A1 (2)
If you switched the parent mapping you could do this:
Declare #Family table (Id int, Name varchar(50), Type int)
Declare #FamilyLink table (Id int, parentId int)
declare #searchvalue varchar(50) = 'AAA'
insert into #Family values (0, 'O', 0)
insert into #Family values (1, 'A', 1)
insert into #Family values (2, 'A1', 2)
insert into #Family values (3, 'AAA', 3)
insert into #Family values (4, 'B', 1)
insert into #Family values (5, 'B1', 2)
insert into #Family values (6, 'BBB', 3)
insert into #FamilyLink values (1, 0)
insert into #FamilyLink values (2, 1)
insert into #FamilyLink values (3, 2)
insert into #FamilyLink values (4, 0)
insert into #FamilyLink values (5, 4)
insert into #FamilyLink values (6, 5)
;WITH CTE AS(
SELECT name, f.id, fl.parentId
FROM #Family f
JOIN #FamilyLink fl ON fl.id = f.Id
WHERE Name = #searchvalue
UNION ALL
SELECT f.Name, f.id, fl.parentId
FROM CTE
JOIN #Family f ON f.id = cte.parentId
JOIN #FamilyLink fl ON fl.id = f.Id
WHERE f.Type > 0
)
SELECT *
FROM CTE
Order by id

How to update date in table based on two criteria from a select

I need to update a date in one table based on if an userID and planName are returned from a select off a different table.
Something like
UPDATE Table A
SET DATE = GETDATE()
WHERE userid AND planName IN (SELECT userid, planName From Table B)
The simplest method is to join these two tables in an UPDATE statement.
Try the following:
UPDATE [Table A]
SET DATE = GETDATE()
FROM [Table A] a
INNER JOIN [Table B] b on a.userid = b.userid and a.planName = b.planName
I think this is what you looking for:
UPDATE A
SET
A.DATE = GETDATE()
FROM TableA AS A
WHERE EXISTS
(
SELECT 1
FROM TableB AS B
WHERE B.userid = A.userid
AND B.planName = A.planName
);
this will update all the rows in your table A that have the exact combination(s) of userid and planName that exist in table B
so if Table A has the following:
userid planName
1 A
2 A
1 B
and Table B has the following
userid planName
1 A
1 B
it will only update the following in Table A:
userid planName
1 A
1 B
See if this helps...
-- some test data...
IF OBJECT_ID('tempdb..#TableA', 'U') IS NOT NULL
DROP TABLE #TableA;
CREATE TABLE #TableA (
UserID INT NOT NULL,
PlanName VARCHAR(5) NOT NULL,
SomeDate DATE NULL,
PRIMARY KEY CLUSTERED (UserID)
);
IF OBJECT_ID('tempdb..#TableB', 'U') IS NOT NULL
DROP TABLE #TableB;
CREATE TABLE #TableB (
UserID INT NOT NULL,
PlanName VARCHAR(5) NOT NULL,
PRIMARY KEY CLUSTERED (UserID, PlanName)
);
INSERT #TableA (UserID, PlanName) VALUES
(1, 'aaa'), (2, 'aab'), (3, 'abb'),
(4, 'aaa'), (5, 'aab'), (6, 'ccc');
INSERT #TableB (UserID, PlanName) VALUES
(1, 'aaa'), (1, 'abb'), (1, 'bbb'),
(2, 'aaa'), (2, 'abb'), (2, 'bbb'),
(3, 'aaa'), (3, 'abb'), (3, 'bbb'),
(4, 'aaa'), (4, 'abb'), (4, 'bbb'),
(5, 'aaa'), (5, 'abb'), (5, 'bbb'),
(6, 'aaa'), (6, 'abb'), (6, 'bbb');
--=========================================
-- check initial values...
SELECT * FROM #TableA ta;
SELECT * FROM #TableB tb;
-- written as a SELECT...
SELECT
*
FROM
#TableA ta
WHERE
EXISTS (SELECT 1 FROM #TableB tb WHERE ta.UserID = tb.UserID AND ta.PlanName = tb.PlanName);
-- written as an UPDATE...
UPDATE ta SET
ta.SomeDate = GETDATE()
FROM
#TableA ta
WHERE
EXISTS (SELECT 1 FROM #TableB tb WHERE ta.UserID = tb.UserID AND ta.PlanName = tb.PlanName);
-- check updated values...
SELECT * FROM #TableA ta;
This was able to get it:
WITH CTE (userid, planName)
AS (SELECT userid, planName From Table B)
UPDATE A
SET DATE = GETDATE()
FROM Table A
JOIN CTE B
ON B.userid = A.userid AND B.planName = A.planName

sql query to join two tables and a boolean flag to indicate whether it contains any words from third table

I have 3 tables with the following schema
create table main (
main_id int PRIMARY KEY,
secondary_id int NOT NULL
);
create table secondary (
secondary_id int NOT NULL,
tags varchar(100)
);
create table bad_words (
words varchar(100) NOT NULL
);
insert into main values (1, 1001);
insert into main values (2, 1002);
insert into main values (3, 1003);
insert into main values (4, 1004);
insert into secondary values (1001, 'good word');
insert into secondary values (1002, 'bad word');
insert into secondary values (1002, 'good word');
insert into secondary values (1002, 'other word');
insert into secondary values (1003, 'ugly');
insert into secondary values (1003, 'bad word');
insert into secondary values (1004, 'pleasant');
insert into secondary values (1004, 'nice');
insert into bad_words values ('bad word');
insert into bad_words values ('ugly');
insert into bad_words values ('worst');
expected output
----------------
1, 1000, good word, 0 (boolean flag indicating whether the tags contain any one of the words from the bad_words table)
2, 1001, bad word,good word,other word , 1
3, 1002, ugly,bad word, 1
4, 1003, pleasant,nice, 0
I am trying to use case to select 1 or 0 for the last column and use a join to join the main and secondary table, but getting confused and stuck. Can someone please help me with a query ? These tables are stored in redshift and i want query compatible with redshift.
you can use the above schema to try your query in sqlfiddle
EDIT: I have updated the schema and expected output now by removing the PRIMARY KEY in secondary table so that easier to join with the bad_words table.
You can use EXISTS and a regex comparison with \m and \M (markers for beginning and end of a word, respectively):
with
main(main_id, secondary_id) as (values (1, 1000), (2, 1001), (3, 1002), (4, 1003)),
secondary(secondary_id, tags) as (values (1000, 'very good words'), (1001, 'good and bad words'), (1002, 'ugly'),(1003, 'pleasant')),
bad_words(words) as (values ('bad'), ('ugly'), ('worst'))
select *, exists (select 1 from bad_words where s.tags ~* ('\m'||words||'\M'))::int as flag
from main m
join secondary s using (secondary_id)
select main_id, a.secondary_id, tags, case when c.words is not null then 1 else 0 end
from main a
join secondary b on b.secondary_id = a.secondary_id
left outer join bad_words c on c.words like b.tags
SELECT m.main_id, m.secondary_id, t.tags, t.is_bad_word
FROM srini.main m
JOIN (
SELECT st.secondary_id, st.tags, exists (select 1 from srini.bad_words b where st.tags like '%'+b.words+'%') is_bad_word
FROM
( SELECT secondary_id, LISTAGG(tags, ',') as tags
FROM srini.secondary
GROUP BY secondary_id ) st
) t on t.secondary_id = m.secondary_id;
This worked for me in redshift and produced the following output with the above mentioned schema.
1 1001 good word false
3 1003 ugly,bad word true
2 1002 good word,other word,bad word true
4 1004 pleasant,nice false

convert marks into percentage

how to convert marks obtained by a student into x%
i.e. there are two exams. calculate certain %marks from both exams (say x% and Y%) so that the total will be 100%
Based on the limited info that you have provided, I think you might be asking for the following:
create table student
(
id int,
s_name varchar(10)
)
insert into student values (1, 'Jim')
insert into student values (2, 'Bob')
insert into student values (3, 'Jane')
create table exams
(
id int,
e_name varchar(10)
)
insert into exams values (1, 'Test 1')
insert into exams values (2, 'Test 2')
insert into exams values (3, 'Test 3')
insert into exams values (4, 'Test 4')
create table exam_student
(
e_id int,
s_id int,
dt datetime,
score decimal(5,2)
)
insert into exam_student values(1, 1, '2012-08-01', 65.0)
insert into exam_student values(1, 2, '2012-08-01', 85.0)
insert into exam_student values(2, 1, '2012-08-02', 75.0)
insert into exam_student values(2, 2, '2012-08-02', 42.0)
select avg(es.score) as ScorePct, s_id, s.s_name
from exam_student es
inner join exams e
on es.e_id = e.id
inner join student s
on es.s_id = s.id
group by s_id, s_name
Results:
If you provide more details on exactly what you are looking for that would be helpful in answering your question.

Generating combinations in SQL Server

I have a table that contains groups ('G1', 'G2' etc) and a table that contains persons ('P1', 'P2', etc...) and a m:m relation ship between them, so one user can belong to several groups, and one group consists of several users.
I have a rule that is satisfied only if a certain number of members of each group is present (i.e. at least 2 members of G1 and at least 1 member of G2 must be present), and I have a list od users that are present. One person cannot fulfil more than one requirement, so if P1 and P2 are members of both G1 and G2, the rule still needs a third person which can be a member of either G1 or G2.
Any ideas how can this be done in SQL Server?
Creation scripts:
create table Groups (GroupID int, Name nvarchar(100))
insert into Groups values (1, 'First')
insert into Groups values (2, 'Second')
insert into Groups values (3, 'Third')
create table Persons (PersonID int, Name nvarchar(100))
insert into Persons values (1, 'One')
insert into Persons values (2, 'Two')
insert into Persons values (3, 'Three')
insert into Persons values (4, 'Four')
insert into Persons values (5, 'Five')
insert into Persons values (6, 'Six')
create table PersonGroups (PersonID int, GroupID int)
-- p1 and p2 are members of g1
insert into PersonGroups values (1, 1)
insert into PersonGroups values (2, 1)
-- p2, p3 and p4 are members of g2
insert into PersonGroups values (2, 2)
insert into PersonGroups values (3, 2)
insert into PersonGroups values (4, 2)
-- p2, p4, p5 and p6 are members of g3
insert into PersonGroups values (2, 3)
insert into PersonGroups values (4, 3)
insert into PersonGroups values (5, 3)
insert into PersonGroups values (6, 3)
So, If a rule needs one person from each group to be present (1,3,5), (1,2,3), (2,3,4) would be valid, and (3, 5, 6) would not be valid.
Create header table for rules
create table #ruleset (Id int, name varchar(100))
insert into #ruleset
select 1,'At least 1 person from each group'
Create child table for each rule having many entries for each group.
drop table #ruleset_grouprules
create table #ruleset_Grouprules(Id int identity(1,1), RuleId int,
GroupID int, MinUsers int, MaxUsers int)
insert into #ruleset_Grouprules (RuleId, groupId, MinUsers, MaxUsers)
select 1,1,1,null
union all
select 1,2,1,null
union all
select 1,3,1,null
You can use NULL in the MinUsers column to represent no minimum amount
You can use NULL in the MaxUsers column to represent no maximum amount
This query will show you whether the group rules have passed or not.
select r.id, r.Name, gr.GroupId,
case when x.GroupQty>=isnull(gr.MinUsers, x.GroupQty)
and x.GroupQty<=isnull(gr.MaxUsers, x.GroupQty)
then 1 else 0 end as GroupValid
from #ruleset r
join #ruleset_Grouprules gr on gr.RuleId=r.Id
join (
select g.groupID, count(*) GroupQty
from #Groups g
join #PersonGroups pg on pg.GroupID=g.GroupID
join #Persons p on p.PersonID=pg.PersonID
group by g.GroupID
)x on x.GroupID=gr.GroupID
You can then aggregate on this query to compare sum(GroupValid)=count(*) with a group by r.id to check if the entire Rule is valid. I left it like that so you can see the working data.