how to convert the result of many tables into one result - sql-server

select sum(value) as sales_value_a from tbl_a
--its result =500
select sum(value) as sales_value_b from tbl_b
--its result =600
select sum(value) as sales_value_c from tbl_c
--its result =300
I want result like = tbl_a + tbl_b - tbl_c
--result =800
none of the queries i have tried are getting the right result. so i seek the humble cooperatiion of the experienced

SELECT (select sum(value) as sales_value_a from tbl_a) +
(select sum(value) as sales_value_b from tbl_b) +
(select sum(value) as sales_value_c from tbl_c) AS result

as mentioned in the comments union all then aggregate
with myTable(Value) as (
select Value from TableA union all
select Value from TableB union all
select Value from TableC
)
select sum(Value) from MyTable
http://sqlfiddle.com/#!18/e63f8/9

Try the below query to handle null. I have multiplied the result of table3 with (-1) as you want to subtract the result of 3rd Table.
SELECT SUM(value) result FROM
(
SELECT COALESCE(sum(value), 0) value FROM tbl_a
UNION
SELECT COALESCE(sum(value), 0) FROM tbl_b
UNION
SELECT (-1)*COALESCE(sum(value), 0) FROM tbl_c
)T

You can go for CROSS JOIN and apply your calculation as given below:
SELECT sum_a + sum_b -sum_c as totalsum
from
(
(select sum(value) as sales_value_a from tbl_a) as a(sum_a)
CROSS JOIN
(select sum(value) as sales_value_b from tbl_b) as b(sum_b)
CROSS JOIN
(select sum(value) as sales_value_c from tbl_c) as c(sum_c)
)
800

Related

Unexpected result using CTE to perform a random join on two tables for all rows one-to-many

I am attempting to randomly join the rows of two tables (TableA and TableB) such that each row in TableA is joined to only one row in TableB and every row in TableB is joined to at least one row in TableA.
For example, a random join of TableA with 5 distinct rows and TableB with 3 distinct rows should result in something like this:
TableA TableB
1 3
2 1
3 1
4 2
5 1
However, sometimes not all the rows from TableB are included in the final result; so in the example above might have row 2 from TableB missing because in its place is either row 1 or 3 joined to row 4 on TableA. You can see this occur by executing the script a number of times and checking the result. It seems that it is necessary for some reason to use an interim table (#Q) to be able to ensure that a correct result is returned which has all rows from both TableA and TableB.
Can someone please explain why this is happening?
Also, can someone please advise on what would be a better way to get the desired result?
I understand that sometimes no result is returned due to a failure of some kind in the cross apply and ordering which i have yet to identify and goes to the point that I am sure there is a better way to perform this operation. I hope that makes sense. Thanks in advance!
declare #TableA table (
ID int
);
declare #TableB table (
ID int
);
declare #Q table (
RN int,
TableAID int,
TableBID int
);
with cte as (
select
1 as ID
union all
select
ID + 1
from cte
where ID < 5
)
insert #TableA (ID)
select ID from cte;
with cte as (
select
1 as ID
union all
select
ID + 1
from cte
where ID < 3
)
insert #TableB (ID)
select ID from cte;
select * from #TableA;
select * from #TableB;
with cte as (
select
row_number() over (partition by TableAID order by newid()) as RN,
TableAID,
TableBID
from (
select
a.ID as TableAID,
b.ID as TableBID
from #TableA as a
cross apply #TableB as b
) as M
)
select --All rows from TableB not always included
TableAID,
TableBID
from cte
where RN in (
select
top 1
iCTE.RN
from cte as iCTE
group by iCTE.RN
having count(distinct iCTE.TableBID) = (
select count(1) from #TableB
)
)
order by TableAID;
with cte as (
select
row_number() over (partition by TableAID order by newid()) as RN,
TableAID,
TableBID
from (
select
a.ID as TableAID,
b.ID as TableBID
from #TableA as a
cross apply #TableB as b
) as M
)
insert #Q
select
RN,
TableAID,
TableBID
from cte;
select * from #Q;
select --All rows from both TableA and TableB included
TableAID,
TableBID
from #Q
where RN in (
select
top 1
iQ.RN
from #Q as iQ
group by iQ.RN
having count(distinct iQ.TableBID) = (
select count(1) from #TableB
)
)
order by TableAID;
See if this gives you what you're looking for...
DECLARE
#CountA INT = (SELECT COUNT(*) FROM #TableA ta),
#CountB INT = (SELECT COUNT(*) FROM #TableB tb),
#MinCount INT;
SELECT #MinCount = CASE WHEN #CountA < #CountB THEN #CountA ELSE #CountB END;
WITH
cte_A1 AS (
SELECT
*,
rn = ROW_NUMBER() OVER (ORDER BY NEWID())
FROM
#TableA ta
),
cte_B1 AS (
SELECT
*,
rn = ROW_NUMBER() OVER (ORDER BY NEWID())
FROM
#TableB tb
),
cte_A2 AS (
SELECT
a1.ID,
rn = CASE WHEN a1.rn > #MinCount THEN a1.rn - #MinCount ELSE a1.rn end
FROM
cte_A1 a1
),
cte_B2 AS (
SELECT
b1.ID,
rn = CASE WHEN b1.rn > #MinCount THEN b1.rn - #MinCount ELSE b1.rn end
FROM
cte_B1 b1
)
SELECT
A = a.ID,
B = b.ID
FROM
cte_A2 a
JOIN cte_B2 b
ON a.rn = b.rn;

How to use CTE to get a query repeated for multiple inputs?

I have the following query:
SELECT **top 1** account, date, result
FROM table_1 as t1
JOIN table_2 at t2 ON t1.accountId = t2.frn_accountId
WHERE accountID = 1
ORDER BY date
This query returns the result that I want however I want that result for multiple accountID. They query should return the top 1 value for each accountID.
The query that produce the list of the accountID-s is:
SELECT accountID from lskin WHERE refname LIKE '%BHA%' and isactive = 1
How can I write this query so it can produce the desired result? I have been playing around with CTE but haven't been able to make it correct. It doesn't have to be with CTE, I just thought it can be easier using CTE...
Here is CTE solution.
SELECT *
FROM (SELECT account
, date
, result
, ROW_NUMBER() OVER (PARTITION BY t1.accountId ORDER BY date DESC) AS Rownum
FROM table_1 AS t1
INNER JOIN table_2 AS t2
ON t1.accountId = t2.frn_accountId
INNER JOIN lskin AS l
ON l.accountID = t1.accountID
WHERE l.refname LIKE '%BHA%'
) a
WHERE a.Rownum = 1;
Use max on your date and group by the account, or what ever columns are appropriate.
SELECT
account,
DT = max(date),
result
FROM table_1 as t1
JOIN table_2 as t2 ON t1.accountId = t2.frn_accountId
JOIN lskin as l on l.accountID = t1.accountID
WHERE l.refname like '%BHA%'
GROUP BY
account
,result
If the grouping isn't correct, just join to a sub-query to limit it with max date. Just change the table names as necessary.
SELECT
account,
date,
result
FROM table_1 as t1
JOIN table_2 as t2 ON t1.accountId = t2.frn_accountId
JOIN lskin as l on l.accountID = t1.accountID
INNER JOIN (select max(date) dt, accountID from table_1 group by accountID) tt on tt.dt = t1.accountId and tt.accountId = t1.accountId
WHERE l.refname like '%BHA%'
Ignore the CTE at the top. That's just test data.
/* CTE Test Data */
; WITH table_1 AS (
SELECT 1 AS accountID, 'acc1' AS account UNION ALL
SELECT 2 AS accountID, 'acc2' AS account UNION ALL
SELECT 3 AS accountID, 'acc3' AS account
)
, table_2 AS (
SELECT 1 AS frn_accountID, 'new1' AS result, GETDATE() AS [date] UNION ALL
SELECT 1 AS frn_accountID, 'mid1' AS result, GETDATE()-1 AS [date] UNION ALL
SELECT 1 AS frn_accountID, 'old1' AS result, GETDATE()-2 AS [date] UNION ALL
SELECT 2 AS frn_accountID, 'new2' AS result, GETDATE() AS [date] UNION ALL
SELECT 2 AS frn_accountID, 'mid2' AS result, GETDATE()-1 AS [date] UNION ALL
SELECT 2 AS frn_accountID, 'old2' AS result, GETDATE()-2 AS [date] UNION ALL
SELECT 3 AS frn_accountID, 'new3' AS result, GETDATE() AS [date] UNION ALL
SELECT 3 AS frn_accountID, 'mid3' AS result, GETDATE()-1 AS [date] UNION ALL
SELECT 3 AS frn_accountID, 'old3' AS result, GETDATE()-2 AS [date]
)
, lskin AS (
SELECT 1 AS accountID, 'purple' AS refName, 1 AS isActive UNION ALL
SELECT 2 AS accountID, 'blue' AS refName, 1 AS isActive UNION ALL
SELECT 3 AS accountID, 'orange' AS refName, 0 AS isActive UNION ALL
SELECT 4 AS accountID, 'blue' AS refName, 1 AS isActive
)
,
/* Just use the below and remove comment markers around WITH to build Orders CTE. */
/* ; WITH */
theCTE AS (
SELECT s1.accountID, s1.account, s1.result, s1.[date]
FROM (
SELECT t1.accountid, t1.account, t2.result, t2.[date], ROW_NUMBER() OVER (PARTITION BY t1.account ORDER BY t2.[date]) AS rn
FROM table_1 t1
INNER JOIN table_2 t2 ON t1.accountID = t2.frn_accountID
) s1
WHERE s1.rn = 1
)
SELECT lskin.accountID
FROM lskin
INNER JOIN theCTE ON theCTE.accountid = lskin.accountID
WHERE lskin.refName LIKE '%blue%'
AND lskin.isActive = 1
;
EDITED:
I'm still making a lot of assumptions about your data structure. And again, make sure you're querying what you need. CTEs are awesome, but you don't want to accidentally filter out expected results.

how to SUM two different columns in two different table between two date

Below is my query:
select sum(tableA.value)+sum(tableB.value1) )
from tableA,tableB
where tableA.data between '2016-01-21' and '2016-03-09'
and tableB.date2 between '2016-01-21' and '2016-03-09'
But the results are wrong when number of rows are different.
Example tableA.value = 2 and tableB values are =3 and 5 the result =12
This is wrong. The result should have been 10
;with sumA as (
select sum(tableA.value) value from tableA
where tableA.data between '2016-01-21' and '2016-03-09'
), sumB as (
select sum(tableB.value) value from tableB
where tableB.date2 between '2016-01-21' and '2016-03-09'
)
select a.Value + b.Value from sumA, sumB;
Please try below query
SELECT
SUM(A.value) OVER (PARTITION BY A.date order by A.date) +
SUM(B.value) OVER (PARTITION BY B.date order by B.date)
FROM
(select value, date from tableA where date between '2016-01-21' and '2016-03-09')A --2, d1
CROSS JOIN
(select value, date from tableB where date between '2016-01-21' and '2016-03-09')B --3,d2 and 5,d3
--Result of CROSS JOIN is below
--2,d1,3,d2
--2,d1,5,d3
-- which gives result as
--2+8=10

MSSQL subquery result to show and calculate

I need show a subquery result and use this same result to calculate other value, is possible set this value in a variable in MS SQL 2008 or something like this?
exemple:
SELECT
#test = (SELECT COUNT(*) FROM [tableTest] WHERE [tableTest].[columnA] = [tableA].[columnA]) as 'Counter'
, (#test * 50) as 'Calc'
, [tableA].[columnA]
FROM tableA
you may use a cte and join on it.
with cte as (select count(*) cnt, columnA from [tableTest] group by columnA)
select
c.cnt as 'Counter',
c.cnt * 50 as 'Calc',
a.columnA
from tableA a
join cte c on c.columnA = a.columnA
It could also be done with a subquery, of course
select
a.columnA,
c.cnt as 'Counter',
c.cnt * 50 as 'Calc'
from tableA a
join (select columnA, count(*) as cnt
from tableTest
group by columnA) c
on c.columnA = a.columnA
Why can't you do this. Move the subquery outside of select statement and store the result in a variable
Then use that variable for calculations.
declare #test int = (SELECT COUNT(*) FROM [tableTest])
SELECT
#test as 'Counter'
, (#test * 50) as 'Calc'
, [tableA].[columnA]
FROM tableA
Update :
SELECT [Counter],
( [Counter] * 50 ) AS 'Calc',
columnA
FROM (SELECT (SELECT Count(*)
FROM [tableTest]
WHERE [tableTest].[columnA] = [tableA].[columnA]) AS 'Counter',
[tableA].[columnA]
FROM tableA) A
You can also use correlated sub-queries:
SELECT
Counter = (SELECT COUNT(*) FROM tableTest t WHERE t.columnA = a.columnA),
Calc = (SELECT COUNT(*) FROM tableTest t WHERE t.columnA = a.columnA) * 50,
a.columnA
FROM tableA a
It'll be optimized to be only evaluated once.
Try:
SELECT t2.[Count]
,t2.[Count] * 50 As [Calc]
,[tableA].[columnA]
FROM TableA
CROSS APPLY
(
SELECT COUNT(*) AS [Count]
FROM TableTest
WHERE [tableTest].[columnA] = [tableA].[columnA]
) t2

Selecting Count from multiple tables and returning them all in one row - SQL Server

so the issue I'm trying to solve is I have 8 tables with data in them. And a 9th table, with a field for each table, that I want to store the count of each of the previous 8 tables. I'm able to return the counts however instead of one count per field, I have 8 rows just populating the first field. Each of the 8 table names is a field name in the 9th table. Here's my code:
SELECT COUNT(SubID) as Sent_Members FROM Sent_Members
UNION ALL
SELECT COUNT(SubID) as Sent_Shoppers FROM Sent_Shoppers
UNION ALL
SELECT COUNT(SubID) as Open_Members FROM Open_Members
UNION ALL
SELECT COUNT(SubID) as Open_Shoppers FROM Open_Shoppers
UNION ALL
SELECT COUNT(SubID) as Click_Members FROM Click_Members
UNION ALL
SELECT COUNT(SubID) as Click_Shoppers FROM Click_Shoppers
UNION ALL
SELECT COUNT(SubID) as Unique_Click_Members FROM Unique_Click_Members
UNION ALL
SELECT COUNT(SubID) as Unique_Click_Shoppers FROM Unique_Click_Shoppers
I'm guessing I should be using something instead of Union, but I'm not sure what that would be.. Thanks!
This looks uglier but it is hundreds of times more efficient than doing 8 subqueries with a complete table scan in each one.
;WITH r AS
(
SELECT t.name, rc = SUM(p.rows)
FROM sys.tables AS t
INNER JOIN sys.partitions AS p
ON t.[object_id] = p.[object_id]
WHERE p.index_id IN (0,1)
AND t.name IN
(
N'Sent_Members',
N'Sent_Shoppers',
N'Open_Members',
N'Open_Shoppers',
N'Click_Members',
N'Click_Shoppers',
N'Unique_Click_Members',
N'Unique_Click_Shoppers'
)
GROUP BY t.name
)
SELECT * FROM r
PIVOT (MAX(rc) FOR name IN
(
[Sent_Members],
[Sent_Shoppers],
[Open_Members],
[Open_Shoppers],
[Click_Members],
[Click_Shoppers],
[Unique_Click_Members],
[Unique_Click_Shoppers]
) AS p;
Here you go:
INSERT INTO [Table9]
SELECT
(SELECT COUNT(*) FROM Sent_Members) AS Sent_Members,
(SELECT COUNT(*) FROM Sent_Shoppers) AS Sent_Shoppers,
(SELECT COUNT(*) FROM Open_Members) AS Open_Members,
(SELECT COUNT(*) FROM Open_Shoppers) AS Open_Shoppers,
(SELECT COUNT(*) FROM Click_Members) AS Click_Members,
(SELECT COUNT(*) FROM Click_Shoppers) AS Click_Shoppers,
(SELECT COUNT(*) FROM Unique_Click_Members) AS Unique_Click_Members,
(SELECT COUNT(*) FROM Unique_Click_Shoppers) AS Unique_Click_Shoppers

Resources