SUM values in last row - sql

I have table with values
+--------+------------+-------------+
| XPK | Money | NumOfDevices|
+--------+------------+-------------+
| 1 | 1000 | 2 |
| 2 | 2000 | 3 |
| 3 | 3000 | 4 |
+--------+------------+-------------+
Need to sum all values and to enter the asterisk "*" in entire row to separate TOTAL Values from other values, so result need to look something like this
+--------+------------+-------------+
| XPK | Money | NumOfDevice |
+--------+------------+-------------+
| 1 | 1000 | 2 |
| 2 | 2000 | 3 |
| 3 | 3000 | 4 |
|***********************************|
| TOTAL | 6000 | 9 |
+--------+------------+-------------+
Any idea ?

The easiest way for this is to use a UNION selecting the totals from the table:
Select Convert(Varchar (10), XPK) XPK,
Money,
NumOfDevices
From YourTable
Union
Select 'TOTAL' As XPK,
Sum(Money),
Sum(NumOfDevices)
From YourTable
Order By Case When XPK = 'TOTAL' Then 1 Else 0 End, XPK
Another method of doing this would be to use a GROUP BY WITH ROLLUP
Select Case When Grouping(XPK) = 1
Then 'TOTAL'
Else Convert(Varchar (10), XPK)
End As XPK,
Sum(Money) Money,
Sum(NumOfDevices) NumOfDevices
From YourTable
Group By XPK With Rollup
Order By Grouping(XPK)

IN Table ERP System SAP
select B.ItemCode as'Item No.',B.Dscription as'Item Description',B.Quantity,B.Price as'Sale Amt',B.LineTotal as'Total'
from ODLN A
inner join DLN1 B On A.DocEntry=B.DocEntry
union all
select 'Total',convert(nvarchar(10),sum(case when b.Dscription is not null then 1 else 0 end)),sum(b.quantity),sum(b.price),sum(b.lineTotal)
from ODLN A
inner join DLN1 B On A.DocEntry=B.DocEntry

Related

Table structure issue - Query Pivot/Unpivot

I am trying to query a table for data conversion but I am running into issues with the structure. I am guessing I need to Pivot then Unpivot but I am not sure where to begin.
This is my current table
+----+-----------+-------+---------+
| ID | field | value | date |
+----+-----------+-------+---------+
| 1 | Draw1 | 1500 | NULL |
| 1 | Draw1Date | NULL | 4/15/16 |
| 1 | Draw1Fee | 100 | NULL |
| 1 | Draw2 | 2000 | NULL |
| 1 | Draw2Date | NULL | 3/14/17 |
| 1 | Draw2Fee | 100 | NULL |
| 2 | Draw1 | 800 | NULL |
| 2 | Draw1Date | NULL | 4/16/18 |
| 2 | Draw1Fee | 150 | NULL |
| 2 | Draw2 | 760 | NULL |
| 2 | Draw2Date | NULL | 5/6/18 |
| 2 | Draw2Fee | 150 | NULL |
+----+-----------+-------+---------+
Result needed
+----+-------+---------+---------+------+
| ID | Draws | Amount | Date | Fee |
+----+-------+---------+---------+------+
| 1 | Draw1 | 1500 | 4/15/16 | 100 |
| 1 | Draw2 | 2000 | 3/14/17 | 100 |
| 2 | Draw1 | 800 | 4/16/18 | 150 |
| 2 | Draw2 | 760 | 5/6/18 | 150 |
+----+-------+---------+---------+------+
My answer works for provided data. if you are looking for more general solution, for more variety of data, you may try to find another answer. I've not used PIVOT/UNPIVOT.
Test Data:
create table #t (ID int, field varchar(20), [value] int, [date] date)
insert into #t values
(1 ,'Draw1' , 1500 , NULL ),
(1 ,'Draw1Date' , NULL , '4/15/16'),
(1 ,'Draw1Fee' , 100 , NULL ),
(1 ,'Draw2' , 2000 , NULL ),
(1 ,'Draw2Date' , NULL , '3/14/17'),
(1 ,'Draw2Fee' , 100 , NULL ),
(2 ,'Draw1' , 800 , NULL ),
(2 ,'Draw1Date' , NULL , '4/16/18'),
(2 ,'Draw1Fee' , 150 , NULL ),
(2 ,'Draw2' , 760 , NULL ),
(2 ,'Draw2Date' , NULL , '5/6/18' ),
(2 ,'Draw2Fee' , 150 , NULL )
Query:
;with ct as (
select ID, field
from #t
where field in ('Draw1', 'Draw2')
group by ID, field
)
select ct.ID, ct.field
, t1.[value] as Amount, t2.[date] as [Date], t3.[value] as Fee
from ct
inner join #t t1 on t1.ID = ct.ID and t1.field = ct.field
inner join #t t2 on t2.ID = ct.ID and t2.field = ct.field + 'Date'
inner join #t t3 on t3.ID = ct.ID and t3.field = ct.field + 'Fee'
Result:
ID field Amount Date Fee
1 Draw1 1500 2016-04-15 100
1 Draw2 2000 2017-03-14 100
2 Draw1 800 2018-04-16 150
2 Draw2 760 2018-05-06 150
Try this...
SELECT tblAmount.id AS ID,
tblAmount.field AS Draws,
Max(tblAmount.value) AS Amount,
Max(tblDate.[date]) AS [Date],
Max(tblFee.value) AS Fee
FROM tablename tblAmount
INNER JOIN (SELECT id, field, [date]
FROM tablename
WHERE [date] IS NOT NULL AND field LIKE '%Date') tblDate
ON tblAmount.id = tblDate.id
AND tblDate.field LIKE tblAmount.field + '%'
INNER JOIN (SELECT id, field, value
FROM tablename
WHERE value IS NOT NULL AND field LIKE '%Fee') tblFee
ON tblAmount.id = tblFee.id
WHERE tblAmount.value IS NOT NULL
AND tblAmount.field NOT LIKE '%Fee'
AND tblAmount.field NOT LIKE '%Date'
GROUP BY tblAmount.id, tblAmount.field
ORDER BY tblAmount.id, tblAmount.field
Output
+----+-------+--------+------------+-----+
| ID | Draws | Amount | Date | Fee |
+----+-------+--------+------------+-----+
| 1 | Draw1 | 1500 | 2016-04-15 | 100 |
| 1 | Draw2 | 2000 | 2017-03-14 | 100 |
| 2 | Draw1 | 800 | 2018-04-16 | 150 |
| 2 | Draw2 | 760 | 2018-05-06 | 150 |
+----+-------+--------+------------+-----+
Demo: http://www.sqlfiddle.com/#!18/97688/101/0
I would simply do:
select id, left(field, 5),
max(case when len(field) = 5 then value end) as value,
max(case when field like '%date' then value end) as date,
sum(case when field like '%fee' then value end) as fee
from t
group by id, left(field, 5);
If your field is really more complex, do you are looking for date and fee at the end, by anything before, then use cross apply:
select t.id, v.draws,
max(case when t.field = v.draws then value end) as value,
max(case when t.field like '%date' then value end) as date,
sum(case when t.field like '%fee' then value end) as fee
from t cross apply
(values (replace(replace(field, 'date', ''), 'fee', '')) v(draws)
group by id, v.draws;

Columns into rows in sql

i would like to ask for help please in sql, I have a table in this form
ID | Indicator1 | Indicator2 | Indicator3 | Indicator4
1 | 1 | 0 | 0 | 0
2 | 0 | 1 | 1 | 0
3 | 1 | 1 | 0 | 0
4 | 0 | 0 | 0 | 0
And I would like to make it look like this
ID | Indicators
1 | Indicator1
2 | Indicator2
2 | Indicator3
3 | Indicator1
3 | Indicator2
4 | NULL
Any suggestions please ? Thank you
Use UNPIVOT.
SELECT p.Id,
p.Indicators,
p.IndicatorsValue
FROM TableName
UNPIVOT
(
IndicatorsValue FOR Indicators IN (Indicator1,Indicator2,Indicator3,Indicator4)
)AS p
select b.* from #temp a left join (
SELECT p.Id,
p.Indicators
FROM #temp
UNPIVOT
(
IndicatorsValue FOR Indicators IN (Indicator1,Indicator2,Indicator3,Indicator4)
)AS p
where p.IndicatorsValue <>0)b on a.id=b.id
Use UNPIVOT and add filter to remove unnecessary columns:
SELECT DISTINCT ID, Indicators
FROM #Indicator
UNPIVOT (IndicatorsValue
FOR Indicators IN (Indicator1,Indicator2,Indicator3,Indicator4)) AS up
WHERE up.IndicatorsValue <> 0

Joining results of two joins

I am looking for the best way to create a query that will do the following(Note: This is just an example, I know this example can be written better, my real goal is a much more complex example, but follows a similar structure)
items
item_id | name | cost
1 | Water | 1.00
2 | Chips | 1.50
trans_local
local_id | item_id | date
1 | 1 | '2018-03-12'
2 | 1 | '2018-03-13'
3 | 2 | '2018-03-13'
trans_international
international_id | item_id | currency | date
1 | 1 | 'GBP' | '2018-03-11'
2 | 2 | 'EUR' | '2018-03-12'
3 | 2 | 'GBP' | '2018-03-12'
I'm looking to create a select statement a table that lists all transactions in it.
local_id | international_id | item_id | item_name | item_cost | currency | date
1 | null | 1 | Water | 1.00 | null | '2018-03-12'
2 | null | 1 | Water | 1.00 | null | '2018-03-13'
3 | null | 2 | Chips | 1.50 | null | '2018-03-13'
null | 1 | 1 | Water | 1.00 | 'GBP' | '2018-03-11'
null | 2 | 2 | Chips | 1.50 | 'EUR' | '2018-03-12'
null | 3 | 2 | Chips | 1.50 | 'GBP' | '2018-03-12'
items should be joined to either trans_local or trans_international. I know I can do this with LEFT OUTER JOIN, but I am unsure how to get results of all transactions together. I believe it would be a FULL JOIN but getting everything together is confusing me a bit. Any help would be greatly appreciated.
I think the the only way to achieve your result is to use a UNION query, something like following:
(
SELECT
NULL as international_id,
trans_local.local_id,
items.name as item_name,
items.cost as item_cost,
NULL as currency,
trans_local.date as date
FROM items
LEFT JOIN trans_local ON items.item_id = trans_local.item_id
)
UNION
(
SELECT
trans_international.international_id as international_id,
NULL as local_id,
items.name as item_name,
items.cost as item_cost,
trans_international.currency as currency,
trans_international.date as date
FROM items
LEFT JOIN trans_international ON items.item_id = trans_international.item_id
)
select local_id , international_id, A.item_id, item_name, item_cost,
currency, B.DATE
from items A
left outer join
trans_local B
on (A.item_id = B.item_id)
left outer join
trans_international C
on (A.item_id = C.item_id)
as per your requirement your item_id column is having all the values. so find the column on table for which u want all the values and make it as left outer join.
I think you want a union all:
select i.*, t.*
from ((select local_id, NULL as internationalid, item_id, null as currency, date
from trans_local
) union all
(select NULL as local_id, internationalid, item_id, currency, date
from trans_international
)
) t join
item i
on t.item_id = i.item_id;

How to merge two different rows(how to assign different value is zero)

I am trying to use union for merging two output but these rows value are different.I need different rows value are zero.like output(third) table.I was struggle with pass two days please help me.
Select t1.round,
t1.SC,
t1.ST,
t1.OTHERS,
t2.round_up,
t2.SC_up,
t2.ST_up,
t2.OTHERS_up
From
(Select round as round,
Sum (non_slsc_qty) as SC,
Sum (non_slst_qty) as ST,
Sum (non_slot_qty) as OTHERS
FROM vhn_issue
where (date between '2015-08-01' and '2015-08-31')AND
dvn_cd='15' AND phc_cd='012' AND hsc_cd='05' GROUP BY round) t1
,
(Select round as round_up,
Sum (non_slsc_qty) as SC_up,
Sum (non_slst_qty) as ST_up,
Sum (non_slot_qty) as OTHERS_up,
FROM vhn_issue
where (date between '2015-04-01' and '2015-08-31')AND
dvn_cd='15' AND phc_cd='012' AND hsc_cd='05' GROUP BY round) t2
This first table result
+-----------------------------------+------------+--------+--------
| round | SC | ST | OTHERS |
+-----------------------------------+------------+--------+--------
| 1 | 20 | 30 | 50 |
| | | | |
| | | | |
+-----------------------------------+------------+--------+--------+
This is second table result
+-----------------------------------+------------+--------+----------
| round_up | SC_up | ST_up | OTHERS_up |
+-----------------------------------+------------+--------+-----------
| 1 | 21 | 31 | 51 |
| 3 | 10 | 5 | 2 |
| | | | |
+-----------------------------------+------------+--------+--------+---
I need output like this
+------------+--------+----------------------------------------------
| round_up | SC | ST |OTHERS | SC_up | ST_up |OTHERS_up |
+------------+--------+-----------------------------------------------
| 1 | 20 | 30 | 50 | 21 | 31 | 51 |
| | | | | | | |
| 3 | 0 | 0 | 0 | 10 | 5 | 2 |
+------------+--------+--------+---------------------------------------
You can use WITH Queries (Common Table Expressions) to wrap the two selects and use RIGHT JOIN to get the desired output,COALESCE is used to print 0 instead of NULL.
WITH a
AS (
SELECT round AS round
,Sum(non_slsc_qty) AS SC
,Sum(non_slst_qty) AS ST
,Sum(non_slot_qty) AS OTHERS
FROM vhn_issue
WHERE (
DATE BETWEEN '2015-08-01'
AND '2015-08-31'
)
AND dvn_cd = '15'
AND phc_cd = '012'
AND hsc_cd = '05'
GROUP BY round
)
,b
AS (
SELECT round AS round_up
,Sum(non_slsc_qty) AS SC_up
,Sum(non_slst_qty) AS ST_up
,Sum(non_slot_qty) AS OTHERS_up
,
FROM vhn_issue
WHERE (
DATE BETWEEN '2015-04-01'
AND '2015-08-31'
)
AND dvn_cd = '15'
AND phc_cd = '012'
AND hsc_cd = '05'
GROUP BY round
)
SELECT coalesce(b.round_up, 0) round_up
,coalesce(a.sc, 0) sc
,coalesce(a.st, 0) st
,coalesce(a.others, 0) others
,coalesce(b.sc_up, 0) sc_up
,coalesce(b.st_up, 0) st_up
,coalesce(b.others_up, 0) others_up
FROM a
RIGHT JOIN b ON a.round = b.round_up
WITH Results_CTE AS
(
Select t1.round as round_up ,
t1.SC as SC,
t1.ST as ST,
t1.OTHERS as OTHERS,
0 as SC_up,
0 as ST_up,
0 as OTHERS_up
from round t1
union all
t2.round_up as round_up ,
0 as SC,
0 as ST,
0 as OTHERS,
t2.SC_up,
t2.ST_up,
t2.OTHERS_up from round t2
)
select round_up , sum(SC) as SC,sum (ST) as ST, sum(OTHERS) as OTHERS, sum(SC_up) as SC_up, sum(ST_up) as ST_up, sum(OTHERS_up) as OTHERS_ up
from Results_CTE group by round_up

get the value from the previous row if row is NULL

I have this pivoted table
+---------+----------+----------+-----+----------+
| Date | Product1 | Product2 | ... | ProductN |
+---------+----------+----------+-----+----------+
| 7/1/15 | 5 | 2 | ... | 7 |
| 8/1/15 | 7 | 1 | ... | 9 |
| 9/1/15 | NULL | 7 | ... | NULL |
| 10/1/15 | 8 | NULL | ... | NULL |
| 11/1/15 | NULL | NULL | ... | NULL |
+---------+----------+----------+-----+----------+
I wanted to fill in the NULL column with the values above them. So, the output should be something like this.
+---------+----------+----------+-----+----------+
| Date | Product1 | Product2 | ... | ProductN |
+---------+----------+----------+-----+----------+
| 7/1/15 | 5 | 2 | ... | 7 |
| 8/1/15 | 7 | 1 | ... | 9 |
| 9/1/15 | 7 | 7 | ... | 9 |
| 10/1/15 | 8 | 7 | ... | 9 |
| 11/1/15 | 8 | 7 | ... | 9 |
+---------+----------+----------+-----+----------+
I've found this article that might help me but this only manipulate one column. How do I apply this to all my column or how can I achieve such result since my columns are dynamic.
Any help would be much appreciated. Thanks!
The ANSI standard has the IGNORE NULLS option on LAG(). This is exactly what you want. Alas, SQL Server has not (yet?) implemented this feature.
So, you can do this in several ways. One is using multiple outer applys. Another uses correlated subqueries:
select p.date,
(case when p.product1 is not null else p.product1
else (select top 1 p2.product1 from pivoted p2 where p2.date < p.date order by p2.date desc)
end) as product1,
(case when p.product1 is not null else p.product1
else (select top 1 p2.product1 from pivoted p2 where p2.date < p.date order by p2.date desc)
end) as product1,
(case when p.product2 is not null else p.product2
else (select top 1 p2.product2 from pivoted p2 where p2.date < p.date order by p2.date desc)
end) as product2,
. . .
from pivoted p ;
I would recommend an index on date for this query.
I would like to suggest you a solution. If you have a table which consists of merely two columns my solution will work perfectly.
+---------+----------+
| Date | Product |
+---------+----------+
| 7/1/15 | 5 |
| 8/1/15 | 7 |
| 9/1/15 | NULL |
| 10/1/15 | 8 |
| 11/1/15 | NULL |
+---------+----------+
select x.[Date],
case
when x.[Product] is null
then min(c.[Product])
else
x.[Product]
end as Product
from
(
-- this subquery evaluates a minimum distance to the rows where Product column contains a value
select [Date],
[Product],
min(case when delta >= 0 then delta else null end) delta_min,
max(case when delta < 0 then delta else null end) delta_max
from
(
-- this subquery maps Product table to itself and evaluates the difference between the dates
select p.[Date],
p.[Product],
DATEDIFF(dd, p.[Date], pnn.[Date]) delta
from #products p
cross join (select * from #products where [Product] is not null) pnn
) x
group by [Date], [Product]
) x
left join #products c on x.[Date] =
case
when abs(delta_min) < abs(delta_max) then DATEADD(dd, -delta_min, c.[Date])
else DATEADD(dd, -delta_max, c.[Date])
end
group by x.[Date], x.[Product]
order by x.[Date]
In this query I mapped the table to itself rows which contain values by CROSS JOIN statement. Then I calculated differences between dates in order to pick the closest ones and thereafter fill empty cells with values.
Result:
+---------+----------+
| Date | Product |
+---------+----------+
| 7/1/15 | 5 |
| 8/1/15 | 7 |
| 9/1/15 | 7 |
| 10/1/15 | 8 |
| 11/1/15 | 8 |
+---------+----------+
Actually, the suggested query doesn't choose the previous value. Instead of this, it selects the closest value. In other words, my code can be used for a number of different purposes.
First You need to add identity column in temporary or hard table then resolved by following method.
--- Solution ----
Create Table #Test (ID Int Identity (1,1),[Date] Date , Product_1 INT )
Insert Into #Test ([Date], Product_1)
Values
('7/1/15',5)
,('8/1/15',7)
,('9/1/15',Null)
,('10/1/15',8)
,('11/1/15',Null)
Select ID , DATE ,
IIF ( Product_1 is null ,
(Select Product_1 from #TEST
Where ID = (Select Top 1 a.ID From #TEST a where a.Product_1 is not null and a.ID<b.ID
Order By a.ID desc)
),Product_1) Product_1
from #Test b
-- Solution End ---