Suppose that we have a sample table
c1 | c2
--------------
a | b
a | b
a | c
a | c
a | c
d | e
d | e
How can we turn this table into the following format
c1 | c2 | c3
--------------------------
a | b | 2
a | c | 3
d | e | 2
where c3 contains the count of c2 based on distinct c1 value.
This is a group by with two keys:
select c1, c2, count(*)
from t
group by c1, c2;
select c1, c2, count(*) as c3
from your_table
group by c1, c2
If I have 4 rows in database like these.
|____A____|____B_____|
| a1 | b1 |
| a2 | b2 |
| a3 | b3 |
| a4 | b4 |
But I need to display 10 rows by added NO column to get serial number for each row like these
__NO__|____A____|____B_____|
1 | a1 | b1 |
2 | a2 | b2 |
3 | a3 | b3 |
4 | a4 | b4 |
5 | | |
6 | | |
7 | | |
8 | | |
9 | | |
10 | | |
How to query by sql server?
Fiddle here : http://sqlfiddle.com/#!3/9a9dd/1
WITH CTE1
AS
(
SELECT 1 AS [NO]
UNION ALL
SELECT [NO]+1 FROM CTE1 WHERE [NO]<10
),
CTE2 AS
(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS RN, A,B
FROM YOURTABLE
)
SELECT C1.[NO],A,B
FROM CTE1 C1 LEFT JOIN CTE2 C2 ON C1.[NO] = C2.RN
Here is another way without using recursive cte and LEFT JOIN.
SQL Fiddle
;WITH Cte AS(
SELECT
NO = ROW_NUMBER() OVER (ORDER BY A, B), A, B
FROM tbl
UNION ALL
SELECT
t.n, NULL, NULL
FROM (VALUES
(11), (12), (13), (14), (15), (16), (17), (18), (19), (20)
)t(n)
),
CteFinal AS(
SELECT *, rn = ROW_NUMBER() OVER (ORDER BY NO)
FROM Cte
)
SELECT
rn AS NO, A, B
FROM CteFinal
WHERE rn < = 10
This the sample of my data:
+----+---+----+----+----+----+----+-------------+------------+-------------+
| ID | C | C1 | C2 | C3 | C4 | C5 | EndingPoint | TransferID | Transferred |
+----+---+----+----+----+----+----+-------------+------------+-------------+
| 1 | A | A | | | | | B | 1 | 80 |
+----+---+----+----+----+----+----+-------------+------------+-------------+
| 2 | A | A | B | | | | C | 2 | 40 |
+----+---+----+----+----+----+----+-------------+------------+-------------+
| 3 | A | A | B | C | | | A | 3 | 10 |
+----+---+----+----+----+----+----+-------------+------------+-------------+
| 4 | B | B | | | | | C | 1 | 25 |
+----+---+----+----+----+----+----+-------------+------------+-------------+
| 5 | B | B | C | | | | A | 2 | 30 |
+----+---+----+----+----+----+----+-------------+------------+-------------+
| 6 | C | C | | | | | A | 1 | 70 |
+----+---+----+----+----+----+----+-------------+------------+-------------+
I need to generate Temporary Table? or WITH clause, that will look like:
In case that TransferID = 1 THEN it will take the string from C1 and EndPoint and value from Transferred:
+------+----+------------+
| From | To |Transferred |
+------+----+------------+
| A | B | 80 |
+------+----+------------+
+------+----+------------+
| From | To |Transferred |
+------+----+------------+
| B | C | 25 |
+------+----+------------+
+------+----+------------+
| From | To |Transferred |
+------+----+------------+
| C | A | 70 |
+------+----+------------+
In case than TransferID=2 THEN: It will take the value from C1 and C2 and value from Transferred.
The next row would be then the value from C2 and EndPoint and value from Transferred:
+------+----+------------+
| From | To |Transferred |
+------+----+------------+
| A | B | 40 |
+------+----+------------+
| B | C | 40 |
+------+----+------------+
+------+----+------------+
| From | To |Transferred |
+------+----+------------+
| B | C | 30 |
+------+----+------------+
| C | A | 30 |
+------+----+------------+
In Case that TransferID=3 THEN: It will take the value from C1 and C2 and value from Transferred.
The next row would be then the value from C2 and C3 and value from Transferred.
The next row would be then the value from C3 and EndPoint and value from Transferred
+------+----+------------+
| From | To |Transferred |
+------+----+------------+
| A | B | 10 |
+------+----+------------+
| B | C | 10 |
+------+----+------------+
| C | A | 10 |
+------+----+------------+
And so on up to TransferID=5
And then from Temporary Table or With Selection (not sure what will work better), I will select the SUM of Transferred, GROUP BY From, To.
I am using MS SQL 2008 and SQL Fiddle is here
Fiddle Code :
Create TABLE T (
ID int NOT NULL,
C varchar(5) NOT NULL,
C1 varchar(5),
C2 varchar(5),
C3 varchar(5),
C4 varchar(5),
C5 varchar(5),
EndingPoint varchar(5) NOT NULL,
TransferID int NOT NULL,
Transferred int);
INSERT INTO T VALUES (1,'A','A','','','','','B',1,80);
INSERT INTO T VALUES (2,'A','A','B','','','','C',2,40);
INSERT INTO T VALUES (3,'A','A','B','C','','','A',3,10);
INSERT INTO T VALUES (4,'B','B','','','','','C',1,25);
INSERT INTO T VALUES (5,'B','B','C','','','','A',2,30);
INSERT INTO T VALUES (6,'C','C','','','','','A',1,70);
Many thanks in advance!
You can implement the logic using a bunch of union all statements:
select c1 as frompt, endingpoint as topt, transferred
from t
where transferred = 1
union all
select c1 as frompt, c2 as topt, transferred
from t
where transferred = 2
union all
select c2 as frompt, endingpoint as topt, transferred
from t
where transferred = 2
union all
select c1 as frompt, c2 as topt, transferred
from t
where transferred = 3
union all
select c2 as frompt, c3 as topt, transferred
from t
where transferred = 3
union all
select c3 as frompt, endingpoint as topt, transferred
from t
where transferred = 3;
This can actually be simplified to:
select (case when transferred = 1 then c1
when transferred = 2 then c2
when transferred = 3 then c3
end) as frompt, endingpoint as topt, transferred
from t
union all
select c1, c2, transferred
from t
where transferred >= 2
union all
select c2, c3, transferred
from t
where transferred >= 3;
Note: the resulting format is more normalized and it is a better structure for the data and the version you are storing.
You can unpivot those C1-EndingPoint columns and then use the Lead function and order by the C1 to EndingPoint column names (which happen to be in correct order)...
http://sqlfiddle.com/#!3/61e519/2
select * from (
select
ID,
[From] = pt,
[To] = Lead(pt, 1) over(partition by Id order by col),
[Transferred]
from
T
unpivot(
pt for col in (C1, C2, C3, C4, C5, EndingPoint)
) unp
where
pt <> ''
) t
where
[To] is not null
SQL 2008 version without using Lead function...
http://sqlfiddle.com/#!3/61e519/5
with cte as (
select
ID,
[From] = pt,
rn = row_number() over(partition by Id order by col),
[Transferred]
from
T
unpivot(
pt for col in (C1, C2, C3, C4, C5, EndingPoint)
) unp
where
pt <> ''
)
select
c.[ID],
c.[From],
[To] = n.[From],
c.[Transferred]
from
cte c
inner join cte n on n.ID = c.ID and n.rn = c.rn + 1
Here is the SQL2008 version of the #dotjo's solution:
;with r as (
select *
from T
unpivot(pt for col in (C1, C2, C3, C4, C5, EndingPoint)) unp
where pt!='')
select r.pt FromPt, r2.pt ToPt, sum(r.Transferred) Transferred
from r
cross apply (select top 1 *
from r r2
where r.ID=r2.ID
and r.col<r2.col
order by r2.col) r2
group by r.pt, r2.pt
When I change my #TransferID to each of your specified numbers(1 through 3), I get the same results you do. Hope this helps!
SQL Server 2005 and Above Solution
DECLARE #TransferID INT = 1;
WITH CTE_Unpivot
AS
(
SELECT EndingPoint,TransferID,val,col,ID,Transferred
FROM T
UNPIVOT
(
val FOR col IN (C1,C2,C3,C4,C5)
) unpvt
WHERE col <= 'C' + CAST(#TransferID AS VARCHAR(5))
AND TransferID <= #TransferID
)
SELECT DISTINCT VAL,CA2.EndingPoint,CA.Transferred
FROM CTE_Unpivot A
CROSS APPLY
(
SELECT TOP 1 Transferred
FROM CTE_Unpivot
WHERE val = A.val
AND col = A.col
AND TransferID = #TransferID
ORDER BY ID
) CA
CROSS APPLY
(
SELECT TOP 1 EndingPoint
FROM CTE_Unpivot
WHERE val = A.val
AND col = A.col
ORDER BY ID
) CA2
WHERE val != ''
I have 2 tables that i want want to join in SQL server 2012. The join must be at the column tblA.customer_id to tblB.customer, after joining the 2 table tblA and tblB, i want if the tblA.date_of_revevenue equals tblB.revenue_date, then add the tblA.revenue + tblB.revenue_amount and display them in 1 row, but and if the tblA.date_of_revevenue differs from tblB.revenue_date then display them in 2 different rows in the result table Tbl_Total_Revenue.
I've passed more than 10 hours trying to join using full outer join but it doesn't work.Please i need your help, guys.
This is the sample tables of what i have and what i am looking for is the result table that looks like the one below.
Thank you
tbl_A
*Customer_id | Date_of_revenue | Revenue
C1 | 201201 | 100
C2 | 201203 | 120.20
C4 | 201304 | 150
C5 | 201401 | 70
tbl_B
*Customer | Revenue_date | Revenue_amount
C1 | 201201 | 50
C2 | 201203 | 200
C3 | 201403 | 250
C5 | 201310 | 50
C4 | 201401 | 20
Result table I want
Tbl_Total_Revenue
*Customer_id | Revenue_date | Total_revenue
C1 | 201201 | 150
C2 | 201203 | 320.20
C3 | 201403 | 250
C4 | 201304 | 150
C4 | 201401 | 20
C5 | 201401 | 70
There is an error in sample data (or expected result), there should be two rows for C5:
select isnull(a.Customer_id, b.Customer), isnull(a.Date_of_revenue, b.Revenue_date),
sum(isnull(a.Revenue,0)+isnull(b.Revenue_amount,0)) as Total_revenue
from tbl_A a
full join tbl_B b on a.Customer_id = b.Customer
and a.Date_of_revenue = b.Revenue_date
group by isnull(a.Customer_id, b.Customer), isnull(a.Date_of_revenue, b.Revenue_date)
order by isnull(a.Customer_id, b.Customer), isnull(a.Date_of_revenue, b.Revenue_date)
Try this:
SELECT Customer_id, Date_of_revenue, SUM(Revenue)
FROM
(
(SELECT Customer_id, Date_of_revenue, Revenue FROM tbl_A)
UNION
(SELECT Customer Customer_id, Revenue_date Date_of_revenue, Revenue_amount Revenue FROM tbl_B)
)
GROUP BY Customer_id, Date_of_revenue
I have two tables History and Historyvalues:
History
HID(uniqeidentifier) | Version(int)
a1 | 1
a2 | 2
a3 | 3
a4 | 4
Historyvalues
HVID(uniqeidentifier) | HID(uniqeidentifier) | ControlID(uniqeidentifier) | Value(string)
b1 | a1 | c1 | value1
b2 | a2 | c1 | value2
b3 | a2 | c2 | value3
Now I Need a query where I can get a list with the last historyvalue of each control from a specific Version like:
Get the last values from Version 3 -> receiving ->
HVID | ControlID | Value
b2 | c1 | value2
b3 | c2 | value3
I tried something like this:
Select HVID, ControlId, max(Version), Value from
(
Select HVID, ControlId, Version, Value
from History inner JOIN
Historyvalues ON History.HID = Historyvalues.HID
where Version <= 3
) as a
group by ControlId
order by Version desc
but this does not work.
Are there any ideas?
Thank you very much for your help.
Best regards
Latest version from each control with your specific Version (WHERE t1.Version <= 3)
Query:
SQLFIDDLEExample
SELECT HVID, ControlId, Version, Value
FROM
(
SELECT t2.HVID, t2.ControlId, t1.Version, t2.Value,
ROW_NUMBER() OVER(PARTITION BY t2.ControlId ORDER BY t1.Version DESC) as rnk
FROM History t1
JOIN Historyvalues t2
ON t1.HID = t2.HID
WHERE t1.Version <= 3
) AS a
WHERE a.rnk = 1
ORDER BY a.Version desc
Result:
| HVID | CONTROLID | VERSION | VALUE |
|------|-----------|---------|--------|
| b2 | c1 | 2 | value2 |
| b3 | c2 | 2 | value3 |
here is your solution
Select Historyvalues.HVID,Historyvalues.ControlID,Historyvalues.Value
from Historyvalues
inner join History on Historyvalues.hid=History.hid
where Historyvalues.hvid in (
select MAX(Historyvalues.hvid) from Historyvalues
inner join History on Historyvalues.hid=History.hid
group by ControlID)