I am working on two tables with column headers ID_1, X1, Value as below
Table 1:
ID_1| X1 | Value
A01 | A | 10
A01 | B | 5
A02 | B | 3
A03 | A | 4
A02 | A | 8
Table 2:
ID_1| X1 | Value
Z01 | A | 7
Z01 | B | 2
Z01 | C | 9
Z03 | A | 1
Z02 | B | 3
Z03 | B | 6
I want to combine these two tables with and additional column with header N at the beginning as below (Expected Output):
N |ID_1| X1 | Value
1 |A01 | A | 10
1 |A01 | B | 5
2 |A02 | B | 3
2 |A02 | A | 8
3 |A03 | A | 4
4 |Z01 | A | 7
4 |Z01 | B | 2
4 |Z01 | C | 9
5 |Z02 | B | 3
6 |Z03 | A | 1
6 |Z03 | B | 6
I think you want union all and dense_rank():
select dense_rank() over (order by id_1) as n,
id_1, x, value
from ((select id_1, x, value from t1
) union all
(select id_1, x, value from t2
)
) t;
Related
I have a SQL Server 2016 temp table that looks like this:
SECTION_NAME SORT_ORDER COL1 COL2 COL3 COL4 COL5 COL6 COL7 COL8 COL9 COL10
ONE 1 A B C D E F G H I J
ONE 2 C D E F G H I X Y Z
I am only selecting the COL columns and want each records COL columns to be on a separate row, like this:
SELECT * FROM #TEMPTABLE
A
B
C
D
E
etc
How can I do that? I don't know PIVOT very well so not sure if I can use that. Thanks!
You need to "unpivot" which I prefer to do using cross apply and values, like this
SELECT
row_number() over (order by SECTION_NAME, SORT_ORDER, ca.value) as ID
, section_name
, sort_order
, ca.value
FROM pivoted
CROSS APPLY (
VALUES
(col1)
, (col2)
, (col3)
, (col4)
, (col5)
, (col6)
, (col7)
, (col8)
, (col9)
, (col10)
) AS ca(value)
which produces:
+----+--------------+------------+-------+
| ID | section_name | sort_order | value |
+----+--------------+------------+-------+
| 1 | ONE | 1 | A |
| 2 | ONE | 1 | B |
| 3 | ONE | 1 | C |
| 4 | ONE | 1 | D |
| 5 | ONE | 1 | E |
| 6 | ONE | 1 | F |
| 7 | ONE | 1 | G |
| 8 | ONE | 1 | H |
| 9 | ONE | 1 | I |
| 10 | ONE | 1 | J |
| 11 | ONE | 2 | C |
| 12 | ONE | 2 | D |
| 13 | ONE | 2 | E |
| 14 | ONE | 2 | F |
| 15 | ONE | 2 | G |
| 16 | ONE | 2 | H |
| 17 | ONE | 2 | I |
| 18 | ONE | 2 | X |
| 19 | ONE | 2 | Y |
| 20 | ONE | 2 | Z |
+----+--------------+------------+-------+
see this demo
I have 2 tables Table A (6 columns 100 rows) and Table B (6 columns 2 rows).
Table A contains the following columns:
Name: same for all rows
Date: chronological dates
V1,V2,V3,V4: 4 columns with numerical values
Table B contains the following columns:
Name: same as table A
Model: 2 different values
V1,V2,V3,V4 : 4 columns with numerical values (values of table A and tableB not same)
TableA:
+------+----------+----+----+----+----+
| Name | Date | V1 | V2 | V3 | V4 |
+------+----------+----+----+----+----+
| abc | 1/12020 | 1 | 2 | 3 | 4 |
| abc | 2/1/2020 | 2 | 3 | 5 | 1 |
| abc | 3/1/2020 | 1 | 4 | 2 | 1 |
+------+----------+----+----+----+----+
Table B:
+------+-------+----+----+----+----+
| Name | Model | V1 | V2 | V3 | V4 |
+------+-------+----+----+----+----+
| abc | AA | 2 | 3 | 1 | 4 |
| abc | BB | 1 | 3 | 4 | 5 |
+------+-------+----+----+----+----+
I need to multiply V1, V2, V3, V4 values of Table B with the same from Table A and create a new table, Table C, where Name, Date, Model, V1, V2, V3, V4 values will be there.
For each date there will be 2 model rows with multiplication results of V1V1, V2V2, V3V3, V4V4. The result will look like below:
Table C:
+------+----------+-------+----+----+----+----+
| Name | Date | Model | V1 | V2 | V3 | V4 |
+------+----------+-------+----+----+----+----+
| abc | 1/1/2020 | AA | 2 | 6 | 3 | 16 |
| abc | 1/1/2020 | BB | 1 | 6 | 12 | 20 |
| abc | 2/1/2020 | AA | 4 | 9 | 5 | 4 |
| abc | 2/1/2020 | BB | 2 | 9 | 20 | 5 |
| abc | 3/1/2020 | AA | 2 | 12 | 2 | 4 |
| abc | 3/1/2020 | BB | 1 | 12 | 8 | 5 |
+------+----------+-------+----+----+----+----+
Try this:
-- Mock-up Data --
DECLARE #TableA table (
[Name] varchar(10), [Date] date, V1 int, V2 int, V3 int, V4 int
);
INSERT INTO #TableA VALUES
( 'abc', '01/01/2020', 1, 2, 3, 4 ),
( 'abc', '02/01/2020', 2, 3, 5, 1 ),
( 'abc', '03/01/2020', 1, 4, 2, 1 );
DECLARE #TableB table (
[Name] varchar(10), Model varchar(2), V1 int, V2 int, V3 int, V4 int
);
INSERT INTO #TableB VALUES
( 'abc', 'AA', 2, 3, 1, 4 ),
( 'abc', 'BB', 1, 3, 4, 5 );
-- Get resultset --
SELECT
a.[Name], a.[Date], b.Model
, b.V1 * a.V1 AS V1
, b.V2 * a.V2 AS V2
, b.V3 * a.V3 AS V3
, b.V4 * a.V4 AS V4
FROM #TableA a
LEFT JOIN #TableB b
ON a.[Name] = b.[Name];
Returns
+------+------------+-------+----+----+----+----+
| Name | Date | Model | V1 | V2 | V3 | V4 |
+------+------------+-------+----+----+----+----+
| abc | 2020-01-01 | AA | 2 | 6 | 3 | 16 |
| abc | 2020-01-01 | BB | 1 | 6 | 12 | 20 |
| abc | 2020-02-01 | AA | 4 | 9 | 5 | 4 |
| abc | 2020-02-01 | BB | 2 | 9 | 20 | 5 |
| abc | 2020-03-01 | AA | 2 | 12 | 2 | 4 |
| abc | 2020-03-01 | BB | 1 | 12 | 8 | 5 |
+------+------------+-------+----+----+----+----+
Note:
I'm sure you know this, however, the LEFT JOIN ensures all data from TableA is returned regardless of a match in TableB. Also, while I didn't do it here, you will probably want to add an ORDER BY.
I have an exported table from accounting software like below.
AccountID AccountName
--------- -----------
11 Acc11
12 Acc12
13 Acc13
11/11 Acc11/11
11/12 Acc11/12
11/111 Acc11/111
11/11/001 Acc11/11/001
11/11/002 Acc11/11/002
12/111 Acc12/111
12/112 Acc12/112
I want to convert it to tree query in MS-SQL Server 2008 to use it as a Treelist datasource in my win aaplication.
I raised this question before and it's answered with a way that it was very very slow for my big table with more than 5000 records (Create Tree Query From Numeric Mapping Table in SQL). But I think counting "/" and separating AccountID field with "/" can solve my problem easier and very faster.
Anyway, My expected result must be like below:
AccountID AccountName ID ParentID Level HasChild
--------- ----------- --- --------- ------ --------
11 Acc11 1 Null 1 1
12 Acc12 2 Null 1 1
13 Acc13 3 Null 1 0
11/11 Acc11/11 4 1 2 1
11/12 Acc11/12 5 1 2 0
11/111 Acc11/111 6 1 2 0
11/11/001 Acc11/11/001 7 4 3 0
11/11/002 Acc11/11/002 8 4 3 0
12/111 Acc12/111 9 2 2 0
12/112 Acc12/112 10 2 2 0
Please Help Me.
I modified my answer given in the first question...
It would be best, if your table would keep the relation data directly in indexed columns. Before you change your table's structure you might try this:
A table with test data
DECLARE #tbl TABLE ( AccountID VARCHAR(100), AccountName VARCHAR(100));
INSERT INTO #tbl VALUES
('11','Acc11')
,('12','Acc12')
,('13','Acc13')
,('11/11','Acc11/11')
,('11/12','Acc11/12')
,('11/111','Acc11/111')
,('11/11/001','Acc11/11/001')
,('11/11/002','Acc11/11/002')
,('12/111','Acc12/111')
,('12/112','Acc12/112');
This will get the needed data into a newly created temp table called #tempHierarchy
SELECT AccountID
,AccountName
,ROW_NUMBER() OVER(ORDER BY LEN(AccountID)-LEN(REPLACE(AccountID,'/','')),AccountID) AS ID
,Extended.HierarchyLevel
,STUFF(
(
SELECT '/' + A.B.value('.','varchar(10)')
FROM Extended.IDsXML.nodes('/x[position() <= sql:column("HierarchyLevel")]') AS A(B)
FOR XML PATH('')
),1,2,'') AS ParentPath
,Extended.IDsXML.value('/x[sql:column("HierarchyLevel")+1][1]','varchar(10)') AS ownID
,Extended.IDsXML.value('/x[sql:column("HierarchyLevel")][1]','varchar(10)') AS ancestorID
INTO #tempHierarchy
FROM #tbl
CROSS APPLY(SELECT LEN(AccountID)-LEN(REPLACE(AccountID,'/','')) + 1 AS HierarchyLevel
,CAST('<x></x><x>' + REPLACE(AccountID,'/','</x><x>') + '</x>' AS XML) AS IDsXML) AS Extended
;
The intermediate result
+-----------+--------------+----+----------------+------------+-------+------------+
| AccountID | AccountName | ID | HierarchyLevel | ParentPath | ownID | ancestorID |
+-----------+--------------+----+----------------+------------+-------+------------+
| 11 | Acc11 | 1 | 1 | | 11 | |
+-----------+--------------+----+----------------+------------+-------+------------+
| 12 | Acc12 | 2 | 1 | | 12 | |
+-----------+--------------+----+----------------+------------+-------+------------+
| 13 | Acc13 | 3 | 1 | | 13 | |
+-----------+--------------+----+----------------+------------+-------+------------+
| 11/11 | Acc11/11 | 4 | 2 | 11 | 11 | 11 |
+-----------+--------------+----+----------------+------------+-------+------------+
| 11/111 | Acc11/111 | 5 | 2 | 11 | 111 | 11 |
+-----------+--------------+----+----------------+------------+-------+------------+
| 11/12 | Acc11/12 | 6 | 2 | 11 | 12 | 11 |
+-----------+--------------+----+----------------+------------+-------+------------+
| 12/111 | Acc12/111 | 7 | 2 | 12 | 111 | 12 |
+-----------+--------------+----+----------------+------------+-------+------------+
| 12/112 | Acc12/112 | 8 | 2 | 12 | 112 | 12 |
+-----------+--------------+----+----------------+------------+-------+------------+
| 11/11/001 | Acc11/11/001 | 9 | 3 | 11/11 | 001 | 11 |
+-----------+--------------+----+----------------+------------+-------+------------+
| 11/11/002 | Acc11/11/002 | 10 | 3 | 11/11 | 002 | 11 |
+-----------+--------------+----+----------------+------------+-------+------------+
And now a similar recursive approach takes place as in my first answer. But - as it is using a real table now and all the string splitting has taken place already - it should be faster...
WITH RecursiveCTE AS
(
SELECT th.*
,CAST(NULL AS BIGINT) AS ParentID
,CASE WHEN EXISTS(SELECT 1 FROM #tempHierarchy AS x WHERE x.ParentPath=th.AccountID) THEN 1 ELSE 0 END AS HasChild
FROM #tempHierarchy AS th WHERE th.HierarchyLevel=1
UNION ALL
SELECT sa.AccountID
,sa.AccountName
,sa.ID
,sa.HierarchyLevel
,sa.ParentPath
,sa.ownID
,sa.ancestorID
,(SELECT x.ID FROM #tempHierarchy AS x WHERE x.AccountID=sa.ParentPath)
,CASE WHEN EXISTS(SELECT 1 FROM #tempHierarchy AS x WHERE x.ParentPath=sa.AccountID) THEN 1 ELSE 0 END AS HasChild
FROM RecursiveCTE AS r
INNER JOIN #tempHierarchy AS sa ON sa.HierarchyLevel=r.HierarchyLevel+1
AND r.AccountID=sa.ParentPath
)
SELECT r.AccountID
,r.AccountName
,r.ID
,r.ParentID
,r.HierarchyLevel
,r.HasChild
FROM RecursiveCTE AS r
ORDER BY HierarchyLevel,ParentID;
And finally I clean up
DROP TABLE #tempHierarchy;
And here's the final result
+-----------+--------------+----+----------+----------------+----------+
| AccountID | AccountName | ID | ParentID | HierarchyLevel | HasChild |
+-----------+--------------+----+----------+----------------+----------+
| 11 | Acc11 | 1 | NULL | 1 | 1 |
+-----------+--------------+----+----------+----------------+----------+
| 12 | Acc12 | 2 | NULL | 1 | 1 |
+-----------+--------------+----+----------+----------------+----------+
| 13 | Acc13 | 3 | NULL | 1 | 0 |
+-----------+--------------+----+----------+----------------+----------+
| 11/11 | Acc11/11 | 4 | 1 | 2 | 1 |
+-----------+--------------+----+----------+----------------+----------+
| 11/111 | Acc11/111 | 5 | 1 | 2 | 0 |
+-----------+--------------+----+----------+----------------+----------+
| 11/12 | Acc11/12 | 6 | 1 | 2 | 0 |
+-----------+--------------+----+----------+----------------+----------+
| 12/111 | Acc12/111 | 7 | 2 | 2 | 0 |
+-----------+--------------+----+----------+----------------+----------+
| 12/112 | Acc12/112 | 8 | 2 | 2 | 0 |
+-----------+--------------+----+----------+----------------+----------+
| 11/11/001 | Acc11/11/001 | 9 | 4 | 3 | 0 |
+-----------+--------------+----+----------+----------------+----------+
| 11/11/002 | Acc11/11/002 | 10 | 4 | 3 | 0 |
+-----------+--------------+----+----------+----------------+----------+
I have a problem on sql server.
How to get running number from foreign key in one time select data from table?
example :
I have one table such as
-----------------
| id | pid | desc |
-----------------
| 1 | 1 | a |
| 2 | 1 | b |
| 3 | 1 | c |
| 4 | 2 | d |
| 5 | 2 | e |
| 6 | 2 | f |
| 7 | 2 | g |
| 8 | 3 | h |
| 9 | 3 | i |
| 10 | 1 | j |
| 11 | 1 | k |
-----------------
I want to get result as below
------------------------
| id | pid | desc | rec |
------------------------
| 1 | 1 | a | 1 |
| 2 | 1 | b | 2 |
| 3 | 1 | c | 3 |
| 4 | 2 | d | 1 |
| 5 | 2 | e | 2 |
| 6 | 2 | f | 3 |
| 7 | 2 | g | 4 |
| 8 | 3 | h | 1 |
| 9 | 3 | i | 2 |
| 10 | 1 | j | 4 |
| 11 | 1 | K | 5 |
------------------------
In above tables foreign key ('pid') Column has values 1 to 3 in different row numbers.
I tried to get the running number from each 'pid' field name.
I havn't found any way to do this,
Can I do that? Can some one help me? am still newbie at sql server
Try this
SELECT
id,
pid,
[desc],
Row_Number() OVER (PARTITION BY pid ORDER BY id) AS rec
FROM <yourtable>
ORDER BY id
You can use Ranking function in SQL Server 2005+ to accomplish that,
So here is your query
Select Row_Number() over (partition by pid order by id) as rec , * from Table
I have a question regarding the pivot function in SQL Server. I have a table which looks like the following:
L | SH | SUM | KTYPE
----------------------
L1 | A | 10 | 1
L1 | B | 12 | 1
L1 | A | 14 | 2
L1 | B | 19 | 2
L2 | A | 9 | 1
L2 | B | 25 | 1
L3 | A | 2 | 1
L3 | B | 2 | 1
L4 | A | 9 | 1
L4 | B | 23 | 1
...
As a result, I would like to have the following structure:
| 1 | 2 | Total |
L | A | B | A | B | A | B |
----------------------------------------
L1 | 10 | 12 | 14 | 19 | 24 | 31 |
L2 | 9 | 25 | 0 | 0 | 9 | 25 |
L3 | 2 | 2 | 0 | 0 | 2 | 2 |
L4 | 9 | 23 | 0 | 0 | 9 | 23 |
...
If I am serious, I have no idea how to do that. I was able to "pivot" the data by KTYPE, but not by KTYPE and SH. Can somebody tell me if this is possible and give me a hint?
Thanks in advance!
tommy
Here is a sample per my comment above about concatenating the fields.
DECLARE #TMP TABLE (L VARCHAR(2), SH VARCHAR(1), SUM INT, KTYPE INT)
INSERT INTO #TMP
SELECT 'L1','A',10,1 UNION ALL
SELECT 'L1','B',12,1 UNION ALL
SELECT 'L1','A',14,2 UNION ALL
SELECT 'L1','B',19,2 UNION ALL
SELECT 'L2','A',9,1 UNION ALL
SELECT 'L2','B',25,1 UNION ALL
SELECT 'L3','A',2,1 UNION ALL
SELECT 'L3','B',2,1 UNION ALL
SELECT 'L4','A',9,1 UNION ALL
SELECT 'L4','B',23,1
SELECT *
FROM (SELECT CAST(KTYPE AS VARCHAR)+SH AS KTYPESH,SUM VAL,L FROM #TMP) DATATABLE
PIVOT (SUM([VAL])
FOR KTYPESH IN ([1A],[1B],[2A],[2B])) PIVOTTABLE