Unite two column tables together within SELECT - sql

How do I unit two tables to a new table that doesn't include a primary key?
For example:
First Table:
Team_Code ID
----------------------------------
433 203994834
436 203994834
436 309228372
435 309228373
434 309228374
433 399064113
Second Table:
number_of_times Team_Code
------------------------------------
3 433
2 434
1 435
1 436
The first lines of the output should look like:
number_of_times Team_Code ID
---------------------------------------------
3 433 203994834
2 434 309228374
1 435 309228373
1 436 203994834

; with
query1 as
(
-- Your Query 1
SELECT * FROM Fireman_Team WHERE Team_Code in (
SELECT Answer.Team_Code FROM Answer WHERE
Answer.Call_Number IN(
SELECT Call_Number FROM (SELECT * FROM Call WHERE Call.Time_Started
BETWEEN ('2016-01-01 00:00:00') AND
('2016-01-31 23:59:59')) AS SSS))
),
query2 as
(
-- Your Query 2
SELECT COUNT(Team_Code) as number_of_times,
Team_Code FROM (SELECT Answer.Team_Code FROM Answer WHERE
Answer.Call_Number IN(
SELECT Call_Number FROM (SELECT * FROM Call WHERE Call.Time_Started
BETWEEN ('2016-01-01 00:00:00') AND
('2016-01-31 23:59:59')) AS SSS)
) AS re GROUP BY Team_Code
)
select *
from query1 q1 inner join query2 q2 on q1.Team_Code = q2.Team_Code

Use CTEs for readability -
WITH CTE1 AS
(
SELECT [Team_Code],[ID] FROM Fireman_Team WHERE Team_Code in (
SELECT Answer.Team_Code FROM Answer WHERE
Answer.Call_Number IN(
SELECT Call_Number FROM (SELECT * FROM Call WHERE Call.Time_Started
BETWEEN ('2016-01-01 00:00:00') AND
('2016-01-31 23:59:59')) AS SSS))
)
;WITH CTE2 AS
(
SELECT COUNT(Team_Code) as number_of_times,
Team_Code FROM (SELECT Answer.Team_Code FROM Answer WHERE
Answer.Call_Number IN(
SELECT Call_Number FROM (SELECT * FROM Call WHERE Call.Time_Started
BETWEEN ('2016-01-01 00:00:00') AND
('2016-01-31 23:59:59')) AS SSS)
) AS re GROUP BY Team_Code
)
SELECT b.[number_of_times], b.[Team_Code], a.[ID]
FROM CTE1 a
INNER JOIN CTE2 b
ON a.[Team_Code] = b.[Team_Code]

Related

SQL query to get both common and and non common data from 2 tables

Hi im looking for a query which will give me both common and non-common data in one query.
Table 2
ID
Assay
1
124
Result
required_missing
required_present
125
124
Based on req_ind column from table 1 , if req_ind is 1 and the same assay is present in table 2 i want to list it as above.
required missing column can have multiple column.
With the data given this gives requested result:
WITH table1 as (
select 1 as ID, 123 as Assay, 0 as req_ind from dual
union all
select 2,124,1 from dual
union all
select 3,125,1 from dual
),
table2 as (
select 1 as ID, 124 as Assay from dual
),
required_missing as (
select
row_number() over (order by table1.Assay) as R,
table1.Assay as required_missing
from table1
left join table2 on table2.Assay = table1.Assay
where table1.req_ind=1 and table2.id is null
),
requires_present as (
select
row_number() over (order by table1.Assay) as R,
table1.Assay as required_present
from table1
left join table2 on table2.Assay = table1.Assay
where table1.req_ind=1 and table2.id is not null
),
results as (
select row_number() over (order by (id)) as r
from table1
)
select rm.required_missing, rp.required_present
from results
left join required_missing rm on rm.R = results.R
left join requires_present rp on rp.R = results.R
where rm.R is not null or rp.R is not null;
output:
REQUIRED_MISSING
REQUIRED_PRESENT
125
124
If you want to have a comma separated list for missing and for present then you can use:
SELECT LISTAGG(CASE WHEN t2.assay IS NULL THEN t1.assay END, ',')
WITHIN GROUP (ORDER BY t1.assay) AS required_missing,
LISTAGG(t2.assay, ',')
WITHIN GROUP (ORDER BY t1.assay) AS required_present
FROM table1 t1
LEFT OUTER JOIN table2 t2
ON (t1.assay = t2.assay)
WHERE t1.req_ind = 1
Which, for the sample data:
CREATE TABLE table1 (id, assay, req_ind) AS
SELECT 1, 123, 0 FROM DUAL UNION ALL
SELECT 2, 124, 1 FROM DUAL UNION ALL
SELECT 3, 125, 1 FROM DUAL UNION ALL
SELECT 4, 126, 1 FROM DUAL UNION ALL
SELECT 5, 127, 1 FROM DUAL;
CREATE TABLE table2 (id, assay) AS
SELECT 1, 124 FROM DUAL UNION ALL
SELECT 2, 127 FROM DUAL;
Outputs:
REQUIRED_MISSING
REQUIRED_PRESENT
125,126
124,127
If you want the output in multiple rows then:
SELECT required_missing,
required_present
FROM (
SELECT NVL2(t2.assay, 'P', 'M') AS status,
ROW_NUMBER() OVER (
PARTITION BY NVL2(t2.assay, 'P', 'M')
ORDER BY t1.assay
) AS rn,
t1.assay
FROM table1 t1
LEFT OUTER JOIN table2 t2
ON (t1.assay = t2.assay)
WHERE t1.req_ind = 1
)
PIVOT (
MAX(assay)
FOR status IN (
'M' AS required_missing,
'P' AS required_present
)
)
Which outputs:
REQUIRED_MISSING
REQUIRED_PRESENT
125
124
126
127
db<>fiddle here

Oracle sql group sum

I have table With ID,Sub_ID and value coloumns
ID SUB_ID Value
100 1 100
100 2 150
101 1 100
101 2 150
101 3 200
102 1 100
SUB ID can vary from 1..maxvalue( In this example it is 3). I need Sum of values for each Sub_ID. If SUB_ID is less than MAXVALUE for a particlaur ID then it should take MAX(SUB_ID) of each ID As shown below ( In this example for ID=100 for SUB_ID 3 it should take 150 i.e 2<3 so value=150))
SUB_ID SUM(values) Remarks
1 300 (100+100+100)
2 400 (150+150+100)
3 450 (150+200+100)
This can be easily done in PL/SQL . Can we use SQL for the same using Model Clause or any other options
SQL Fiddle
Oracle 11g R2 Schema Setup:
CREATE TABLE TableA ( ID, SUB_ID, Value ) AS
SELECT 100, 1, 100 FROM DUAL
UNION ALL SELECT 100, 2, 150 FROM DUAL
UNION ALL SELECT 101, 1, 100 FROM DUAL
UNION ALL SELECT 101, 2, 150 FROM DUAL
UNION ALL SELECT 101, 3, 200 FROM DUAL
UNION ALL SELECT 102, 1, 100 FROM DUAL
Query 1:
WITH sub_ids AS (
SELECT LEVEL AS sub_id
FROM DUAL
CONNECT BY LEVEL <= ( SELECT MAX( SUB_ID ) FROM TableA )
),
max_values AS (
SELECT ID,
MAX( VALUE ) AS max_value
FROM TableA
GROUP BY ID
)
SELECT s.SUB_ID,
SUM( COALESCE( a.VALUE, m.max_value ) ) AS total_value
FROM sub_ids s
CROSS JOIN
max_values m
LEFT OUTER JOIN
TableA a
ON ( s.SUB_ID = a.SUB_ID AND m.ID = a.ID )
GROUP BY
s.SUB_ID
Results:
| SUB_ID | TOTAL_VALUE |
|--------|-------------|
| 1 | 300 |
| 2 | 400 |
| 3 | 450 |
Try this
SELECT SUB_ID,SUM(values),
(SELECT DISTINCT SUBSTRING(
(
SELECT '+'+ CAST(values AS VARCHAR)
FROM table_Name AS T2
WHERE T2.SUB_ID = d.SUB_ID
FOR XML PATH ('')
),2,100000)[values]) as values
FROm table_Name d
GROUP BY SUB_ID
How about something like this:
select max_vals.sub_id, sum(nvl(table_vals.value,max_vals.max_value)) as sum_values
from (
select all_subs.sub_id, t1.id, max(t1.value) as max_value
from your_table t1
cross join (select sub_id from your_table) all_subs
group by all_subs.sub_id, t1.id
) max_vals
left outer join your_table table_vals
on max_vals.id = table_vals.id
and max_vals.sub_id = table_vals.sub_id
group by max_vals.sub_id;
The inner query gets you a list of all sub_id/id combinations and their fall-back values. The out query uses an nvl to use the table value if it exists and the fall-back value if it doesn't.

adding a value to a column from data in next row sql

Base Table
id line_number
1 1232
2 1456
3 1832
4 2002
I wish to add values to a new table such that the next row's value becomes the value in a new column with the last row's value being same..
The final output I need to produce is:
id line_number end_line_number
1 1232 1456
2 1456 1832
3 1832 2002
4 2002 2002
The database is sql server.
Any help is sincerely appreciated.
Thanks
After SQL Server 2012, you can use LEAD like this.
;WITH BaseTable as
(
SELECT 1 id, 1232 line_number
UNION ALL SELECT 2 , 1456
UNION ALL SELECT 3, 1832
UNION ALL SELECT 4 , 2002
)
SELECT id,line_number,(LEAD(line_number,1,line_number) OVER(ORDER BY id ASC))
FROM BaseTable
For previous versions, try this
;WITH BaseTable as
(
SELECT 1 id, 1232 line_number
UNION ALL SELECT 2 , 1456
UNION ALL SELECT 3, 1832
UNION ALL SELECT 4 , 2002
), OrderedBaseTable as
(
SELECT id,line_number,ROW_NUMBER() OVER(ORDER BY id asc) rw
FROM BaseTable
)
SELECT t1.id,t1.line_number,ISNULL(t2.line_number,t1.line_number) next_line_number
FROM OrderedBaseTable t1
LEFT JOIN OrderedBaseTable t2
ON t1.rw = t2.rw - 1
Try this
With T as (
Select id, line_number, Row_Number() OVER(Order By id) + 1 As TempId From TableName)
Select T1.id, T1.line_number, ISNULL(T2.line_number,T1.line_number) As end_line_number From T T1
Left Join T T2 on T2.id = T1.TempId
SQL Fiddle Demo

ParentChild to get correct ID in T-SQL

I have two tables toplevel and parentchild. parentchild table is a tree which is related to each other. Tree looks like this.
TREE
1
-11
2
-12
--13
3
-14
--15
---16
drop table #TopLevel
create table #TopLevel
(
TopLevelID INT,
createdate DateTime
)
insert into #TopLevel
(TopLevelID,createdate
)
select 1,'2013-03-01 00:00:00' union all
select 2,'2013-03-07 00:00:00' union all
select 3,'2013-03-06 00:00:00' union all
select 4,'2013-03-03 00:00:00' union all
select 5,'2013-03-08 00:00:00' union all
select 6,'2013-03-09 00:00:00' union all
select 7,'2013-03-10 00:00:00'
drop table #parentchild
create table #parentchild
(
parentchildID INT,Parent INT,Child INT
)
insert into #parentchild
(
parentchildID,Parent, Child
)
select 1,1,11 union all
select 2,12,13 union all
select 4,15,16 union all
select 5,14,15 union all
select 3,2,12 union all
select 6,3,14
;with abc as
(
select * From #parentchild
left outer join #TopLevel on #parentchild.Parent=#TopLevel.TopLevelID
)
select * from abc
I need to find toplevelid for each row in #parentchild table. For examble in #parentchild table parent=12 is not in #toplevel table because its child too. then if we see child =12 and parent is 2, that is in #toplevel table.
please help. Thanks.
Data should be look like this in #parentchild table. * one i added manually.
parentchildID Parent Child TopLevelID createdate
1 1 11 1 2013-03-01 00:00:00.000
2 12 13 *2 *2013-03-07 00:00:00.000
4 15 16 *3 *2013-03-06 00:00:00.000
5 14 15 *3 *2013-03-06 00:00:00.000
3 2 12 2 2013-03-07 00:00:00.000
6 3 14 3 2013-03-06 00:00:00.000
Where I am doing wrong?
;with abc as
(
select ParentChildID,Parent,Child,TopLevelID,CreateDate From #parentchild
left outer join #TopLevel on #parentchild.Parent=#TopLevel.TopLevelID
)
,xyz as
(
select ParentChildID,Parent,Child,TopLevelID,CreateDate from abc where TopLevelID IS NULL
union all
select a.ParentChildID,a.Parent,a.Child,a.TopLevelID,a.CreateDate from abc a
inner join abc e on e.TopLevelID=a.Parent
)
select * from xyz
This CTE is for first #parentchild table but giving nothing.
;with abc as
(
select ParentChildID,Parent,Child from #parentchild
where parent is null
union all
select a.ParentChildID,a.Parent,a.Child from #parentchild a
inner join abc e on e.child=a.parent
)
select * from abc
I think the recursive common table expression will be your friend here. http://www.codeproject.com/Articles/683011/How-to-use-recursive-CTE-calls-in-T-SQL
Try this. It was a bit of a rush but feel free to clean it up and play around with it. There's probably a more elegant way of doing this than using the left function.
With CTE as (
select parentchildID,Parent,Child,1 as lev,cast(parent as varchar(20)) as heirarchy--,parent as TopParent
from #parentchild pc
join #TopLevel tl on tl.TopLevelID = pc.Parent
union all
select pc2.parentchildID,pc2.Parent,pc2.Child,cte.lev + 1,cast(cte.heirarchy + '\'+ cast(pc2.Child as varchar(3)) as varchar(20))
from #parentchild pc2
join CTE on cte.child = pc2.Parent
where pc2.parent not in (select TopLevelID from #TopLevel)
),
NoDate as
(
select parentchildID,parent,Child,heirarchy,
case left(heirarchy,charindex('\',heirarchy)) when '' then heirarchy else left(heirarchy,charindex('\',heirarchy)-1) end as TopLevelParent
from CTE
)
select nd.parentchildID,nd.Parent,nd.Child,nd.TopLevelParent,tl.createdate,nd.heirarchy
from NoDate nd
join #TopLevel tl on tl.TopLevelID = nd.TopLevelParent
order by parentchildID;

count of Balance installments

i got a requirement to write a MS-SQL stored procedure, the requirement is
Table 1
It consists total student fee to be paid in installments
EX:
SID SNAME INST.Date Amount
123 XYZ 01-01-2013 3500
123 XYZ 01-05-2013 3500
123 XYZ 01-10-2013 3500
123 XYZ 01-04-2014 3500
123 XYZ 01-06-2014 3500
`
Table 2
It consists Payment recd details
SID SNAME Paydate amoount
123 XYZ 01-01-2013 1167
123 XYZ 01-02-2013 1167
123 XYZ 01-03-2013 1167
123 XYZ 01-05-2013 1750
123 XYZ 01-05-2013 1750
123 XYZ 01-10-2013 1167
123 XYZ 01-10-2013 1167
now the requirement is as on jan2014,how many installment to paid,what is the Recd amount, no of balance installments to be paid as on jan-14.
Expected output
SID Sname Total Inst.Amt as on01.01.2014 Paid.amount Balance amt Balance.Installments
123 XYZ 10500 9335 1165 1
For reference I gave one student data.
The stored procedure should run for 36000 students.
Here's a query that will give you what you want, expect Balance.Installments I don't know what it means :
SELECT distinct t1.SID
, t1.SNAME
, t1.Total_Inst
, t2.Paid_amount AS 'Paid.Amount'
, t1.Total_Inst - t2.Paid_amount as 'Balance amt'
, CEILING( (t1.Total_Inst - t2.Paid_amount) / t.Amount ) as 'Balance.Installments'
FROM
table_1 as t
JOIN
( SELECT SID, SNAME, SUM(Amount) as Total_Inst
FROM table_1
WHERE Date < STR_TO_DATE('01/01/2014', '%m/%d/%Y') group by SID, SNAME
)
ON ( t1.SID = t.SID AND t1.SNAME = t.SNAME )
AS t1
LEFT JOIN
( SELECT SID, SNAME, SUM(Amount) as Paid_amount
FROM table_2
WHERE Paydate < STR_TO_DATE('01/01/2014', '%m/%d/%Y') group by SID, SNAME
) AS t2
ON ( t1.SID = t2.SID AND t1.SNAME = t2.SNAME )
why you will need to run for 36000 record at one time.Also what is actially installment.There is only one instalment for any student no several.So i think database is lil wrong.
There should only one instalment amount and time interval(due date) per student in table.
Check the latest change.It is only for one student .
Declare #student table(SID int,SNAME varchar(50),INST Date ,Amount int)
insert into #student
select 123,'XYZ','01-01-2013',3500 union all
select 123, 'XYZ', '01-05-2013', 3500 union all
select 123, 'XYZ', '01-10-2013', 3500 union all
select 123, 'XYZ', '01-04-2014', 3500 union all
select 123, 'XYZ', '01-06-2014', 3500
Declare #instalmentamount float
select #instalmentamount=amount from #student where sid=123
--select #instalmentamount
Declare #Table2 table(SID int,Paydate date,amoount int)
insert into #Table2
select 123, '01-01-2013', 1167 union all
select 123, '01-02-2013', 1167 union all
select 123, '01-03-2013', 1167 union all
select 123, '01-05-2013', 1750 union all
select 123, '01-05-2013', 1750 union all
select 123, '01-10-2013', 1167 union all
select 123, '01-10-2013', 1167
declare #input date='01-01-2014'
;With CTE as
(select s.SID, sum(s.amount) as [Total Inst.Amt ] from #student s
where s.INST<=#input
group by s.SID),
cte1 as
(
select t.SID, sum(t.amoount) as [Paid.amount] from #Table2 t
where t.Paydate<=#input
group by t.SID
)
select c.sid,
(select top 1 s.SNAME from #student s where s.SID=c.SID) [Name],
c.[Total Inst.Amt ],c1.[Paid.amount],
c.[Total Inst.Amt ]-c1.[Paid.amount] [BalanceAmount],cast(((c.[Total Inst.Amt ]-c1.[Paid.amount])/#instalmentamount) as int)+1 [Balance.Installments]
from CTE c inner join cte1 c1 on c.SID=c1.SID
TRY THIS...
SELECT t.ID,
T.SNAME,
T.AMT 'Total Inst.Amt as on01.01.2014',
ISNULL(SUM(amoount),0) AS 'PAID AMT',
T.AMT - ISNULL(SUM(amoount),0) AS 'BALANCE AMT' ,
CEILING((T.AMT- ISNULL(SUM(amoount),0) )/( T.InstAmt*1.)) 'Balance.Installments'
FROM
(
SELECT ID,SNAME,SUM(AMT)AMT,MAX(AMT) AS InstAmt FROM #Table1 WHERE DT_ < '01-31-2014' GROUP BY ID,SNAME
) T
LEFT JOIN #Table2 P ON P.ID = T.id AND P.Paydate < '01-31-2014'
GROUP BY t.ID,SNAME,t.InstAmt,T.AMT