Perform a function after union of two tables - sql

I have two tables that I want to union together then perform some math functions on the combined table.
I know how to do the math for each separate table, but throwing in a union table to go off of is out of my league.
Here's the math for one table using column header "UnitsReceived" and "AsnPsUnits"
The other table would have headers: "cUnitsReceived" and "cAsnPsUnits"
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from VenTest2
where ID<20
group by VendName
How would I perform this function after the union of two tables?

You'll need to get the unioned tables into some table object before performing your function. This could be done using:
A Common Table Expression
with cte as (
select ID, VALUE from A
union all
select ID, VALUE from B
)
select
*
,myfunction(VALUE) as MyFunctionResult
from
cte
A temp table
select ID, VALUE into #myTempTable from A
insert into #myTempTable select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTempTable
A table variable
declare #myTableVariable table (ID int, VALUE decimal)
insert into #myTableVariable
select ID, VALUE from A
union all
select ID, VALUE from B
select
*
,myfunction(VALUE) as MyFunctionResult
from
#myTableVariable
A sub query
select
*
,myfunction(VALUE) as MyFunctionResult
from
(
select ID, VALUE from A
union all
select ID, VALUE from B
) mySubQuery

This will help with the subq being the union
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(5,0))) - (cast(sum(AsnPsUnits) as decimal(5,0)))) /(cast(sum(AsnPsUnits) as decimal(5,0)))) as ASNpsAcc
from
(
select ID, UnitsReceived, AsnPsUnits from VenTest2 where ID<20
union
select ID1, UnitsReceived1, AsnPsUnits1 from VenTest1
)a
group by VendName

This is not the way, brothers:
select VendName,
1-abs(((cast(sum(UnitsReceived) as decimal(10,2))) - (cast(sum(AsnPsUnits) as decimal(10,2)))) /(cast(sum(AsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from VenTest2
where ID<10
group by VendName
union
select cVendName,
1-abs(((cast(sum(cUnitsReceived) as decimal(10,2))) - (cast(sum(casnpsunits) as decimal(10,2)))) /(cast(sum(cAsnPsUnits) as decimal(10,2)))) as ASNpsAcc
from CTest
where id <10
group by cvendname

Related

I want to retrieve max value from two column - SQL table

Please find attached image for table structure
You could try using UNION ALL for build a unique column result and select the max from this
select max(col)
from (
select col1 col
from trans_punch
union all
select col2
from trans_punch) t
You can use a common table expression to union the columns, then select the max.
;with cteUnionPunch(Emp_id, both_punch) AS
(
SELECT Emp_id, In_Punch FROM trans_punch
UNION ALL
SELECT Emp_id, Out_Punch FROM trans_punch
)
SELECT Emp_id, max(both_punch) FROM cteUnionPunch GROUP BY Emp_id
You can use apply :
select tp.Emp_id, max(tpp.Punchs)
from trans_punch as tp cross apply
( values (In_Punch), (Out_Punch) ) tpp(Punchs)
group by tp.Emp_id;

Merge three tables in Select query by rule 3, 2, 1 records from each table

Merge three tables in a Select query by rule 3, 2, 1 records from each table as follows:
TableA: ID, FieldA, FieldB, FieldC,....
TableB: ID, FieldA, FieldB, FieldC,....
TableC: ID, FieldA, FieldB, FieldC,....
ID : auto number in each table
FieldA will be unique in all three tables.
I am looking for a Select query to merge three tables as follows:
TOP three records from TableA sorted by ID
TOP two records from TableB sorted by ID
TOP 1 record from TableC sorted by ID
Repeat this until select all records from all three tables.
If some table has fewer records or does not meet the criteria, ignore that and continue with others.
My attempt:
I did it totally through programming way, like cursors and If conditions inside a SQL Server stored procedure.
It makes delay.
This requires a formula that takes row numbers from each table and transforms it into a series of integers that skips the desired values.
In the query below, I am adding some CTE for the sake of shortening the formula. The real magic is in the UNION. Also, I am adding an additional field for your control. Feel free to get rid of it.
WITH A_Aux as (
SELECT 'A' As FromTable, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum, TableA.*
FROM TableA
), B_Aux AS (
SELECT 'B' As FromTable, ROW_NUMBER() OVER (ORDER BY ID) AS RowNum, TableB.*
FROM TableB
), C_Aux AS (
SELECT 'C' As FromTable, ROW_NUMBER() OVER (Order BY ID) AS RowNum, TableC.*
FROM TableC
)
SELECT *
FROM (
SELECT RowNum+3*FLOOR((RowNum-1)/3) As ColumnForOrder, A_Aux.* FROM A_Aux
UNION ALL
SELECT 3+RowNum+4*FLOOR((RowNum-1)/2), B_Aux.* FROM B_Aux
UNION ALL
SELECT 6*RowNum, C_Aux.* FROM C_Aux
) T
ORDER BY ColumnForOrder
PS: note the pattern Offset + RowNum + (6-N) * Floor((RowNum-1)/N) to group N records together (it of course simplifies a lot for TableC).
PPS: I don't have a SQL server at hand to test it. Let me know if there is a syntax error.
You may try this..
GO
select * into #temp1 from (select * from table1) as t1
select * into #temp2 from (select * from table2) as t2
select * into #temp3 from (select * from table3) as t3
select * into #final from (select col1, col2, col3 from #temp1 where 1=0) as tb
declare #i int
set #i=1
while( (select COUNT(*) from #temp1)>#i)
Begin
;with ct1 as (
select ROW_NUMBER() over (order by id) as Slno, * from #temp1
),ct2 as (
select ROW_NUMBER() over (order by id) as Slno, * from #temp2
),ct3 as (
select ROW_NUMBER() over (order by id) as Slno, * from #temp3
),cfinal as (
select top 3 * from #temp1
union all
select top 2 * from #temp2
union all
select top 1 * from #temp3
)
insert into #final ( col1 , col2, col3 )
select col1, col2, col3 from cfinal
delete from #temp1 where id in (select top 3 ID from #temp1)
delete from #temp2 where id in (select top 2 ID from #temp2)
delete from #temp3 where id in (select top 1 ID from #temp3)
set #i = #i+1
End
Select * from #final
Drop table #temp1
Drop table #temp2
Drop table #temp3
GO
First create temp table for all 3 tables with each insert delete the inserted record and this will result you the desired result, if nothing is missing from my side.
Please see to this if this works.
There is not a lot of information to go with here, but I assume you can use UNION to combine multiple statements.
SELECT * TableA ORDER BY ID DESC OFFSET 3 ROWS
UNION
SELECT * TableB ORDER BY ID DESC OFFSET 2 ROWS
UNION
SELECT * TableC ORDER BY ID DESC OFFSET 1 ROWS
Execute and see if this works.
/AF
From my understanding, I create three temp tables as ta, tb, tc.
select * into #ta from (
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
union all
select 'A' a
) a
select * into #tb from (
select 'B' b
union all
select 'B'
union all
select 'B'
union all
select 'B'
union all
select 'B'
) b
select * into #tc from (
select 'C' c
union all
select 'C'
union all
select 'C'
union all
select 'C'
union all
select 'C'
) c
If tables match you tables, then the output looks like A,A,A,B,B,C,A,A,A,B,B,C,A,B,C,C,C
T-SQL
declare #TAC int = (select count (*) from #ta) -- Table A Count = 7
declare #TBC int = (select count (*) from #tb) -- Table B Count = 5
declare #TAR int = #TAC % 3 -- Table A Reminder = 1
declare #TBR int = #TBC % 2 -- Table B Reminder = 1
declare #TAQ int = (#TAC - #TAR) / 3 -- Table A Quotient = (7 - 1) / 3 = 2, is will passed on NTILE
-- So we gonna split as two group (111), (222)
declare #TBQ int = (#TBC - #TBR) / 2 -- Table B Quotient = (5 - 1) / 2 = 2, is will passed on NTILE
-- So we gonna split as two group (11), (22)
select * from (
select *, NTILE (#TAQ) over ( order by a) FirstOrder, 1 SecondOrder from (
select top (#TAC - #TAR) * from #ta order by a
) ta -- 6 rows are obtained out of 7.
union all
select *, #TAQ + 1, 1 from (
select top (#TAR) * from #ta order by a desc
) ta -- Remaining one row is obtained. Order by desc is must
-- Here FirstOrder is next value of previous value.
union all
select *, NTILE (#TBQ) over ( order by b), 2 from (
select top (#TBC - #TBR) * from #tb order by b
) tb
union all
select *, #TBQ + 1, 2 from (
select top (#TBR) * from #tb order by b desc
) tb
union all
select *, ROW_NUMBER () over (order by c), 3 from #tc
) abc order by FirstOrder, SecondOrder
Let me explain the T-SQL:
Before that, FYR: NTILE and Row Number
Get the count.
Find the Quotient which will pass to NTILE function.
Order by the NTILE value and static.
Note:
I am using SQL Server 2017.
If T-SQL works fine, then you need to change the column in order by <yourcolumn>.

Sum union values

I am trying to sum two values across a UNION. Like:
SELECT
sum(target_value) FROM table
UNION ALL
SELECT
sum(target_value) FROM table_2
But rather than getting the 2 sum values, I want them to also be summed.
How should I go about doing this?
You can try using this in a subquery and calculate at the outer query. Ensure you use UNION ALL to evade the duplicate check
SELECT SUM(a) target_value
FROM
(SELECT
sum(target_value) a FROM table
UNION ALL
SELECT
sum(target_value) a FROM table_2) ;
You can use the WITH clause to do this:
WITH CTE AS (SELECT SUM(target_value) as FirstSum
FROM table
UNION
SELECT
SUM(target_value) as FirstSum
FROM table_2)
SELECT SUM(FirstSum) AS TotalSum FROM CTE
Please see the example below:
create table #temp (x int)
create table #temp2 (x2 int)
insert into #temp values (2)
insert into #temp values (3)
insert into #temp2 values (5)
insert into #temp2 values (6)
select t.col1,t.col2,t.col1+t.col2 as Total
from (
SELECT (select sum(x) FROM #temp) as col1,
(select sum(x2) FROM #temp2) as col2
) t

SQL Server query for getting single value from each column into a single column

I'll start directly by explaining with an example. Suppose I have a table which has 3 columns as shown.
Now what I am trying to achieve is, I want the first values of each individual column into a single column. So it would be something like this,
I have tried a few queries here including using TOP 1 and other incorrect ways. But I am still missing something here to achieve the exact output.
Need some guidance here on how to achieve this. Thank you.
SAMPLE TABLE
SELECT * INTO #TEMP
FROM
(
SELECT 1 BATCH_ID,'AAA' ASSIGNMENTTITLE,'FILE' ASSIGNMENTTYPE
UNION ALL
SELECT 1,'AAA1','FILE'
UNION ALL
SELECT 1,'AAA','FILE'
)TAB
If you need the second row specifically you can do the below
QUERY
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)) FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTITLE FROM CTE WHERE RNO=2
UNION ALL
SELECT ASSIGNMENTTYPE FROM CTE WHERE RNO=2
Click here to view result
UPDATE
Since there are 3 items in each record, it can be puzzled unless and otherwise an a column is for each items in a record.
;WITH CTE AS
(
-- Order row according to default format
SELECT ROW_NUMBER() OVER(ORDER BY (SELECT(0))) RNO,*
FROM #TEMP
)
SELECT CAST(BATCH_ID AS VARCHAR(20)),RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTITLE,RNO
FROM CTE
UNION ALL
SELECT ASSIGNMENTTYPE,RNO
FROM CTE
ORDER BY RNO
Click here to view result
You can use the concat() function to create a column consisting of all the desired values
More info here
Simply you can try this. If want specific for a row use rowid. For all columns Use unpivot
create table #temp(id int, name varchar(100), title varchar(100))
insert into #temp values(1,'aaa','file')
insert into #temp values(1,'aaas','filef')
insert into #temp values(1,'aaaww','filefs')
select * from #temp
select top 1 cast(id as varchar) title from #temp
union
select top 1 name from #temp
union
select top 1 title from #temp
drop table #temp
This might help you
select top 1 convert(varchar(10), batch_id) ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTITLE from table
union all
select top 1 ASSIGNMENTTYPE from table
If this is really what you want: "I want the first values of each individual column into a single column" it would be:
select ASSIGNMENTTITLE
from (
select min(convert(varchar(10), batch_id)) ASSIGNMENTTITLE,
1 ColOrder from table
union all
select min(ASSIGNMENTTITLE),
2 ColOrder from table
union all
select min(ASSIGNMENTTYPE),
3 ColOrder from table
) as data
order by ColOrder

How to avoid Sorting in Union ALL

MY question is simple, How do you avoid the automatic sorting which the UNION ALL query does?
This is my query
SELECT * INTO #TEMP1 FROM Final
SELECT * INTO #TEMP2 FROM #TEMP1 WHERE MomentId = #MomentId
SELECT * INTO #TEMP3 FROM #TEMP1 WHERE RowNum BETWEEN #StartRow AND #EndRow
SELECT * INTO #TEMP4 FROM (SELECT *FROM #TEMP3 UNION ALL SELECT *FROM #TEMP2) as tmp
SELECT DISTINCT * FROM #TEMP4
I'm using SQL Server 2008. I need the Union ALL to perform like a simple Concatenate, which it isn't! Appreciate your help in this.
I think you're mistaken on which operation is actually causing the sort. Check the code below, UNION ALL will not cause a sort. You may be looking at the DISTINCT operation, which uses a sort (it sorts all items and the eliminates duplicates)
CREATE TABLE #Temp1
(
i int
)
CREATE TABLE #temp2
(
i int
)
INSERT INTO #Temp1
SELECT 3 UNION ALL
SELECT 1 UNION ALL
SELECT 8 UNION ALL
SELECT 2
INSERT INTO #Temp2
SELECT 7 UNION ALL
SELECT 1 UNION ALL
SELECT 5 UNION ALL
SELECT 6
SELECT * INTO #TEMP3
FROM (SELECT * FROM #Temp1 UNION ALL SELECT * FROM #temp2) X
UNION ALL adds all the records where as UNION adds only new/distinct records.
Since you are using UNION ALL and using DISTINCT soon after, I think you are looking for UNION
SELECT * INTO #TEMP4 FROM
(
SELECT * FROM #TEMP3
UNION --JUST UNION
SELECT * FROM #TEMP2
) AnotherTemp
Or you can simplify it as
SELECT * INTO #TEMP4 FROM
SELECT DISTINCT *
FROM Final
WHERE MomentId = #MomentId OR RowNum BETWEEN #StartRow AND #EndRow
I'm not familiar with SQL-Server, but you might get my idea
select *, 'A' tid, rownumber() tno from tableA
union all
select *, 'B', rownumber() from tableB
order by tid, tno;
This should get you all records of tableA in their specific order, followed by all records of tableB in their specific order.