Table-1:
kode | 101 | 102 | 103 | 104
=================================
1234 | 100 | 200 | 300 | 400
4555 | 1200 | 130 | 14500 | 1550
5012 | 100 | 150 | 350 | 440
Table-2:
kode | field1 | field2
=======================
1234 | 101 | 100
1234 | 102 | 200
1234 | 103 | 300
1234 | 104 | 400
4555 | 101 | 1200
4555 | 102 | 130
4555 | 103 | 14500
4555 | 104 | 1550
5012 | 101 | 100
5012 | 102 | 150
5012 | 103 | 350
5012 | 104 | 440
I have data in table-1, how to insert data from table-1 totable-2
with use sql query like unpivot to pivot which dynamic by using set #cols
You can use UNPIVOT to create the dataset you want. Let's say your tables looked like this:
create table table1 (
kode int,
[101] int,
[102] int,
[103] int,
[104] int
);
insert into table1 values
(1234 , 100 , 200 , 300 , 400),
(4555 , 1200 , 130 , 14500 , 1550),
(5012 , 100 , 150 , 350 , 440);
Your query will look like this
SELECT kode, field1, field2
FROM table1
UNPIVOT
(
field2 FOR field1 IN ([101], [102], [103], [104])
) AS up;
That will give you the desired result.
Let's way you have a new table like this
create table table2 (
kode int,
field1 int,
field2 int
);
Populate UNPIVOT'ed data into table2
insert into table2
SELECT kode, field1, field2
FROM table1
UNPIVOT
(
field2 FOR field1 IN ([101], [102], [103], [104])
) AS up;
select * from table2;
Example: https://rextester.com/YPWG93602
Related
I have a query that returns an entire row and I need to pivot this result into a new table.
SELECT id_no, stud_name, group_no, class_1, class_2, class_3, class_4 FROM tbl_stud_class
This returns the following:
| id_no | stud_name | group_no | class_1 | class_2 | class_3 | class 4 |
| 1 | John Doe | A11 | 84 | 60 | 80 | 79 |
I need to be able to return this row as:
| id_no | stud_name | group_no | class | grade |
| 1 | John Doe | A11 | class_1 | 84 |
| 1 | John Doe | A11 | class_2 | 60 |
| 1 | John Doe | A11 | class_3 | 80 |
| 1 | John Doe | A11 | class_4 | 79 |
Can someone point me to a way to do this please?
I am converting my PostgreSQL function (where i'm using CROSS JOIN LATERAL to SQL Server)
Thank you!
Just another option is using a CROSS APPLY
Example
Select A.id_no
,A.stud_name
,A.group_no
,B.*
From YourTable A
Cross Apply ( values ('class_1',class_1)
,('class_2',class_2)
,('class_3',class_3)
,('class_4',class_4)
) B(class,grade)
Returns
id_no stud_name group_no class grade
1 John Doe A11 class_1 84
1 John Doe A11 class_2 60
1 John Doe A11 class_3 80
1 John Doe A11 class_4 79
You can use UNPIVOT to get this done in SQL Server. Below is an example using your sample data.
CREATE TABLE #tbl_stud_class
(
id_no int,
stud_name varchar(50),
group_no varchar(50),
class_1 int,
class_2 int,
class_3 int,
class_4 int
)
INSERT INTO #tbl_stud_class VALUES (1, 'John Doe', 'A11', 84, 60, 80, 79)
SELECT *
FROM #tbl_stud_class
UNPIVOT
(
Class FOR Classes IN (class_1, class_2, class_3, class_4)
) AS UP
DROP TABLE #tbl_stud_class
Based on your example, I'd do something like this:
Select
id_no
, stud_name
, group_no
, 'class_1'
, class_1 as grade
From tbl_stud_class
Union All
Select
id_no
, stud_name
, group_no
, 'class_2'
, class_2 as grade
From tbl_stud_class
Union All
etc.
I would also use the full word "student" in my table and field names, but that's not really a database issue... ;)
I have the following:
OrderID | Articlenumber|
--------+--------------+
1 | 123 |
2 | 222 |
1 | 799 |
1 | 987 |
2 | 444 |
3 | 212 |
2 | 222 |
1 | 898 |
and I want the following (sum up all article numbers per orderID):
orderID|articelnumber |
-------+--------------------+
1 |123, 799, 987, 898 |
2 |222, 444, 222 |
3 |212 |
or:
orderID|articelnumber|articelnumber|articelnumber |articelnumber |
-------+-------------+-------------+--------------+--------------+
1 |123 |799 |987 | 898 |
2 |222 |444 |222 | |
3 |212 | | | |
How can I do it with SQL-Server? The number of articles per orderID is variable.
Thanks a lot!
Is something like this what you want?
;WITH cte AS
(
SELECT OrderID, Articlenumber
FROM [YOUR_TABLE]
)
SELECT
OrderID,
STUFF((SELECT ',' + Articlenumber FROM [YOUR_TABLE] WHERE [YOUR_TABLE].OrderID = cte.OrderID FOR XML PATH('')), 1, 1, '') articelnumber
FROM cte
GROUP BY OrderID
ORDER BY 1
Sample data on
MAIN_TABLE:
+-----+--------+-------+
| ID | HEIGHT | STOCK |
+-----+--------+-------+
| ID1 | 180 | 680 |
| ID1 | 170 | 680 |
| ID1 | 130 | 360 |
| ID2 | 250 | 420 |
| ID2 | 190 | 420 |
| ID2 | 70 | 120 |
| ... | ... | ... |
+-----+--------+-------+
I need to select distinct ID rows that have max STOCK with the min HEIGHT.
The desired result would be:
+-----+--------+-------+
| ID | HEIGHT | STOCK |
+-----+--------+-------+
| ID1 | 170 | 680 |
| ID2 | 190 | 420 |
| ... | ... | ... |
+-----+--------+-------+
Query code, that i'm using to achieve it:
WITH MAX_STOCK (ID, maxstock) as
(
select ID, max(STOCK) as maxstock
from MAIN_TABLE
group by ID
),
TABLE_STOCK (ID, HEIGHT, STOCK) AS
(
select a.ID, a.HEIGHT, a.STOCK
from MAIN_TABLE a join MAX_STOCK b
on a.ID= b.ID and a.STOCK = b.maxstock
),
MIN_HEIGHT (ID, minheight) as
(
select ID, min(HEIGHT) as minheight
from TABLE_STOCK
group by ID
),
TABLE_HEIGHT (ID, HEIGHT, STOCK) AS
(
select a.ID, a.HEIGHT, a.STOCK
from TABLE_STOCK a join MIN_HEIGHT b
on a.ID= b.ID and a.HEIGHT = b.minheight
)
If I select any of tables MAX_STOCK, TABLE_STOCK, MIN_HEIGHT,
i have results in 1-2seconds time.
But when selecting TABLE_HEIGHT, which would be my desired result,
It is executing 6min+ with no answer on data with 600 rows
How should i write this query to have the result in reasonable time?
I think you can use window functions to achieve this. Try following example.
create table #Main(
Id varchar(50),
HEIGHT int,
STOCK int
)
insert into #Main values('ID1',180,680),('ID1',170,680),('ID1',130,360 ),('ID2',250,420),('ID2',190,420),('ID2',70,120)
select * from (
select *,dense_rank() over(partition by Id order by STOCK desc,HEIGHT asc) as sira
from #Main
) k
where sira=1
I have 2 tables, ord_tbl and pay_tbl. o_tbl with these data.
ord_tbl
invoice | emp_id | prod_id | amount
123 | 101 | 1 | 1000
123 | 101 | 2 | 500
123 | 101 | 3 | 500
124 | 101 | 2 | 300
125 | 102 | 3 | 200
pay_tbl
invoice | new_invoice | amount
123 | 321 | 300
123 | 322 | 200
124 | 323 | 300
125 | 324 | 100
I would like the selection statement to give me this result
invoice | emp_id | orig_amt | balance | status
123 | 101 | 2000 | 1500 | unsettled
The invoice that has 0 balance will not be included anymore. I know that I have to use the join and sub queries here but I don't even know how to start it! For me, as a beginner, this is very complex already. This is what I tried so far...
SELECT
ord_tbl.invoice,
SUM(ord_tbl.amount) As 'origAmt',
SUM(pay_tbl.amount) As 'payAmt',
origAmt - payAmt As 'bal'
FROM
ord_tbl
INNER JOIN pay_tbl
ON ord_tbl.invoice = pay_tbl.invoice
WHERE
ord_tbl.emp_id = #emp_id AND
bal != 0
GROUP BY
ord_tbl.invoice
You need to prepare your data joining on a non unique field will lead to a cross JOIN,that`s why you get 4000
;WITH CTE as
(SELECT ot.invoice,MAX(ot.emp_id) as emp_id,SUM(ot.amount) as origAmt FROM ord_tbl ot GROUP BY ot.invoice),
CTE2 as
( SELECT pt.invoice,SUM(pt.ammount) as payAmt FROM pay_tbl pt GROUP BY pt.invoice)
SELECT CTE.invoice,CTE.emp_id,CTE.origAmt,CTE.origAmt-NULLIF(CTE2.payAmt,0) as bal,'unsettled' as status
FROM
CTE LEFT JOIN CTE2 ON CTE.invoice=CTE2.invoice
AND CTE.emp_id=101 AND CTE.origAmt-NULLIF(CTE2.payAmt,0)>0
I have a table output like....
srno billno particular Qty rate vat amount paid balance
1 25 aaa 5 20 5 105 400 135
2 25 qqq 5 50 5 225 400 135
3 25 fff 10 20 5 205 400 135
4 26 aaa 10 20 5 205 300 245
5 26 fff 10 20 5 205 300 245
but I want output like:
srno billno particular Qty rate vat amount paid balance
1 25 aaa 5 20 5 105 400 135
qqq 5 50 5 225
fff 10 20 5 205
2 26 aaa 10 20 5 205 300 245
fff 10 20 5 205
How to get this output with a T-SQL select command....
You should be able to do this by using the ranking functions row_number() and dense_rank:
select
case when rn = 1 then cast(rnk as varchar(10)) else '' end srno,
case when rn = 1 then cast(billno as varchar(10)) else '' end billno,
[particular],
[Qty],
[rate],
[vat],
[amount],
case when rn = 1 then cast([paid] as varchar(10)) else '' end [paid],
case when rn = 1 then cast([balance] as varchar(10)) else '' end [balance]
from
(
select [srno], [billno], [particular], [Qty], [rate], [vat], [amount], [paid], [balance],
row_number() over(partition by billno order by srno) rn,
dense_rank() over(order by billno) rnk
from yourtable
) src;
See SQL Fiddle with Demo
The result is:
| SRNO | BILLNO | PARTICULAR | QTY | RATE | VAT | AMOUNT | PAID | BALANCE |
---------------------------------------------------------------------------
| 1 | 25 | aaa | 5 | 20 | 5 | 105 | 400 | 135 |
| | | qqq | 5 | 50 | 5 | 225 | | |
| | | fff | 10 | 20 | 5 | 205 | | |
| 2 | 26 | aaa | 10 | 20 | 5 | 205 | 300 | 245 |
| | | fff | 10 | 20 | 5 | 205 | | |