add column values of two tables that have the same date - sql

for example, I have 2 tables
resto1
day 1 = 1 2 3 4
resto2
day 1 = 5 6 7 8
I wanted to add the values of the first two columns that have the same date the result would be:
day_1_earned = 6 8 10 12
please help

assuming both the tables have a date column, let say named dt_col you can use below query to achieve the required result
select t1.column1+t2.column2 added_values from
table1 t1,table2 t2
where t1.dt_col = t2.dt_col;

SELECT T1.Column1 + T2.Column As TotalColumn
From T1, T2 WHERE T1.Date= T2.Date

SELECT Cr_date, SUM(Column1) Column1, SUM(Column2) Column2
FROM
(
SELECT Cr_Date,Column1,Column2 FROM #T1
UNION
SELECT Cr_Date,Column1,Column2 FROM #T2
) as res
GROUP BY Cr_Date

Related

How to extract multiple rows from a table based on values from multiple columns from another table and then concatenate in SQL?

I have two tables, Table 1 and Table 2. Table 1 have columns "start" and "end" . Table 2 has column "position" and "Sequence". I would like to extract the sequences from Table 2 from position = start to position = end and the create a new column with the concatenated string.
Table 1
Start
End
100
104
105
109
Table 2
Position
Seq
100
A
101
T
102
C
103
T
104
G
105
T
106
T
107
G
108
T
109
G
My final result needs to be
Start
End
Sequence
100
104
ATCTG
105
109
TTGTG
I tried concatenating the values in the Table 2 using the below statement
SELECT Sequence = (Select '' + Seq
from Table2
where Position >= 100 and Position <= 104
order by Position FOR XML PATH('')
)
You don't state what DBMS you are using so here is a SQL Server solution using a CTE and FOR XML to perform the transpose:
; WITH SequenceCTE AS
(
SELECT [Start],
[End],
Seq
FROM Table1 a
JOIN Table2 b
ON b.Position >= a.[Start] AND
b.Position <= a.[End]
)
SELECT DISTINCT
a.[Start],
a.[End],
(
SELECT STUFF(',' + Seq,1,1,'')
FROM SequenceCTE b
WHERE a.[Start] = b.[Start] AND
a.[End] = b.[end]
FOR XML PATH ('')
)
FROM SequenceCTE a
In standard SQL, you can do something like this:
select t1.start, t1.end,
listagg(t2.position, '') within group (order by t2.seq) as sequence
from table1 t1 join
table2 t2
on t2.position between t1.start and t2.end
group by t1.start, t1.end;
Most databases support aggregate string concatenation, but the function may have a different name and slightly different syntax.
Note that start and end are poor names for columns because they are SQL keywords -- as is sequence in most databases.
You can generate row numbers for your first table which can later be used to group the ranges after joining on those numbers:
with to_id as (select row_number(*) over (order by t1.start) id, t1.* from table1 t1),
ranges as (select t3.id, t2.* from table2 t2 join to_id t3 on t3.start <= t2.position and t2.position <= t3.end)
select t3.start, t3.end, group_concat(r1.seq, '') from ranges r1 join to_id t3 on r1.id = t3.id group by r1.id;
Look into how crosstab queries are done.

SQL Server - How to check if a value does not exist in other rows of the same table for same column values?

Following are the two tables in SQL Server: TABLE_A and TABLE_B
I need to get the output as follows:
Get IDs from TABLE_A where Exist = 0
We would get 100, 101 & 102
Now, among 100, 101 & 102, no other rows (in the same table) with the same ID value should have Exist = 1
Hence, 100 can't be selected as it has Exist = 1 in the 2nd row.
So, only 101 & 102 remain
With the remaining ID values (101 & 102), check against the ID column in TABLE_B where 'Exist' column value should not be equal to '1' in any of the rows
In TABLE_B, 4th row has Exist = 1 for 102. So, that can't be selected
We have only 101 now. This is required output and that should be selected.
Could you let me know how to write the simplest query to achieve this please? Let me know if the question needs to be improved.
You can use exists & not exists :
with t as (
select t1.*
from t1
where exists (select 1 from t1 t11 where t11.id = t1.id and t11.exists = 0) and
not exists (select 1 from t1 t11 where t11.id = t1.id and t11.exists = 1)
)
select t.*
from t
where not exists (select 1 from t2 where t.id = t2.id and t2.exists = 1);
Try:
SELECT
ID,
SUM(CAST(Exist AS int)) AS [Exists]
FROM
TABLE_A
GROUP BY ID
HAVING SUM(CAST(Exist AS bit)) = 0
will give you the answer to the first part. You can then JOIN this to a similar query for TABLE_B. That is a "simple" way to show how this works. You can write more complex queries as that from #Yogest Sharma
Like #Peter Smith mentioned, you can use the aggregate function SUM. Note that you would need a cast since you cannot use the aggregate function on a field that has a BIT datatype
;WITH CTE AS
(
SELECT ID, SUM(CAST(Exist AS INT)) AS AggExist FROM TABLE_A GROUP BY ID
UNION
SELECT ID, SUM(CAST(Exist AS INT)) As AggExist FROM TABLE_B GROUP BY ID
)
SELECT ID, SUM(AggExist) FROM CTE GROUP BY ID
HAVING SUM(AggExist) = 0
Here is the demo

SQL recursion query

I am stuck with an issue here.
I have the following table
ID TX_NAME DT_DATE ID_SUCCESSOR
1 Task 1 Jan/01/2012 2
2 Task 2 Jan/02/2012 3
3 Task 3 Jan/01/2012
My objective is to create an SQL statement which brings me TX_NAME which its DT_DATE is later and its ID_SUCCESSOR.
For example, ID = 2 is the one I am looking for as it happens after its successor (ID = 3)
Is it possible in a single query?
Thanks
select t.* from
TestTable t
inner join TestTable t2 on t2.id = t.ID_SUCCESSOR
where t.DT_DATE > t2.DT_DATE
Not tested, but ought to be ok :)
SELECT TX_NAME
from MyTable T1
where DT_DATE > (
SELECT DT_DATE
from MyTable T2
where T1.ID_SUCCESSOR = T2.ID
)

Calculate multiple columns with each other using CTE

I want to build columns that calculated with each other. (Excuse my English)
Example:
Id Column1 Column2 Column3
1 5 5 => Same as Column1 5 => Same as Column2
2 2 12 => column1 current + column2.prev + column3.previous = 2+5+5 17 => column2.current + column3.prev = 12+5
3 3 32 => 3+12+17 49 => 32+17
easier way to see:
Id Column1 Column2 Column3
1 5 5 => Same as Column1 5 => Same as Column2
2 2 12 => 2+5+5 17 => 12+5
3 3 32 => 3+12+17 49 => 32+17
so complicated??? :-(
The previous issue was calculating Column3 with the new calculated column as Column2. But now, it must be renew with the just calculated Column2 and the previous record of Column3 as well. If you want to have a look at the previous post, here it is.
Here is my previous recursive CTE code. It works like, 1st, calculate column2 with previous record of current column (c.Column2) in cteCalculation, and then calculate new column3 in cte2 with just calculated column2 from cteCalculation.
/copied from that previous post/
;with cteCalculation as (
select t.Id, t.Column1, t.Column1 as Column2
from table_1 t
where t.Id = 1
union all
select t.Id, t.Column1, (t.Column1 + c.Column2) as Column2
from table_1 t
inner join cteCalculation c
on t.Id-1 = c.id
),
cte2 as(
select t.Id, t.Column1 as Column3
from table_1 t
where t.Id = 1
union all
select t.Id, (select column2+1 from cteCalculation c where c.id = t.id) as Column3
from table_1 t
inner join cte2 c2
on t.Id-1 = c2.id
)
select c.Id, c.Column1, c.Column2, c2.column3
from cteCalculation c
inner join cte2 c2 on c.id = c2. id
Now I wanna extend it like calculate 2 columns with the data from each other. Means, use 2nd to calc the 3rd, and use 3rd to get new 2nd column data. Hope you can get it.
This is an example how to achive this using recursive CTE
create table #tmp (id int identity (1,1), Column1 int)
insert into #tmp values(5)
insert into #tmp values(2)
insert into #tmp values(3);
with counter as
(
SELECT top 1 id, Column1, Column1 as Column2, Column1 as Column3 from #tmp
UNION ALL
SELECT t.id, t.Column1,
t.Column1 + counter.Column2 + counter.Column3,
(t.Column1 + counter.Column2 + counter.Column3) + counter.Column3 FROM counter
INNER JOIN #tmp t ON t.id = counter.id + 1
)
select * from counter
You'll need to use a Recursive CTE since the values of subsequent columns are dependent upon earlier results.
Do this in pieces, too. Have your first query just return the correct values for Column1. Your next (recursive CTE) query will add the results for Column2, and so on.
OK I'm assuming you're doing inserts into column 1 here of various values.
Essentially col2 always = new col1 value + old col2 value + old col 3 value
col3 = new col2 value + old col3 value
so col3 = (new col1 value + old col2 value + old col 3 value) + old col3 value
So an INSTEAD OF Insert trigger is probably the easiest way to implement.
CREATE TRIGGER tr_xxxxx ON Tablename
INSTEAD OF INSERT
AS
INSERT INTO Tablename (Column1, Column2, Column3)
SELECT ins.col1, ins.col1+t.col2+t.col3, ins.col1+t.col2+t.col3+t.col3
FROM Tablename t INNER JOIN Inserted ins on t.Id = ins.Id
The trigger has access to both the existing (old) values in Tablename t, and the new value being inserted (Inserted.col1).

SELECT DISTINCT for data groups

I have following table:
ID Data
1 A
2 A
2 B
3 A
3 B
4 C
5 D
6 A
6 B
etc. In other words, I have groups of data per ID. You will notice that the data group (A, B) occurs multiple times. I want a query that can identify the distinct data groups and number them, such as:
DataID Data
101 A
102 A
102 B
103 C
104 D
So DataID 102 would resemble data (A,B), DataID 103 would resemble data (C), etc. In order to be able to rewrite my original table in this form:
ID DataID
1 101
2 102
3 102
4 103
5 104
6 102
How can I do that?
PS. Code to generate the first table:
CREATE TABLE #t1 (id INT, data VARCHAR(10))
INSERT INTO #t1
SELECT 1, 'A'
UNION ALL SELECT 2, 'A'
UNION ALL SELECT 2, 'B'
UNION ALL SELECT 3, 'A'
UNION ALL SELECT 3, 'B'
UNION ALL SELECT 4, 'C'
UNION ALL SELECT 5, 'D'
UNION ALL SELECT 6, 'A'
UNION ALL SELECT 6, 'B'
In my opinion You have to create a custom aggregate that concatenates data (in case of strings CLR approach is recommended for perf reasons).
Then I would group by ID and select distinct from the grouping, adding a row_number()function or add a dense_rank() your choice. Anyway it should look like this
with groupings as (
select concat(data) groups
from Table1
group by ID
)
select groups, rownumber() over () from groupings
The following query using CASE will give you the result shown below.
From there on, getting the distinct datagroups and proceeding further should not really be a problem.
SELECT
id,
MAX(CASE data WHEN 'A' THEN data ELSE '' END) +
MAX(CASE data WHEN 'B' THEN data ELSE '' END) +
MAX(CASE data WHEN 'C' THEN data ELSE '' END) +
MAX(CASE data WHEN 'D' THEN data ELSE '' END) AS DataGroups
FROM t1
GROUP BY id
ID DataGroups
1 A
2 AB
3 AB
4 C
5 D
6 AB
However, this kind of logic will only work in case you the "Data" values are both fixed and known before hand.
In your case, you do say that is the case. However, considering that you also say that they are 1000 of them, this will be frankly, a ridiculous looking query for sure :-)
LuckyLuke's suggestion above would, frankly, be the more generic way and probably saner way to go about implementing the solution though in your case.
From your sample data (having added the missing 2,'A' tuple, the following gives the renumbered (and uniqueified) data:
with NonDups as (
select t1.id
from #t1 t1 left join #t1 t2
on t1.id > t2.id and t1.data = t2.data
group by t1.id
having COUNT(t1.data) > COUNT(t2.data)
), DataAddedBack as (
select ID,data
from #t1 where id in (select id from NonDups)
), Renumbered as (
select DENSE_RANK() OVER (ORDER BY id) as ID,Data from DataAddedBack
)
select * from Renumbered
Giving:
1 A
2 A
2 B
3 C
4 D
I think then, it's a matter of relational division to match up rows from this output with the rows in the original table.
Just to share my own dirty solution that I'm using for the moment:
SELECT DISTINCT t1.id, D.data
FROM #t1 t1
CROSS APPLY (
SELECT CAST(Data AS VARCHAR) + ','
FROM #t1 t2
WHERE t2.id = t1.id
ORDER BY Data ASC
FOR XML PATH('') )
D ( Data )
And then going analog to LuckyLuke's solution.