Transposing rows to columns using self join - sql

I have a table named category with values as below,
CategoryId | Value | Flag
1 25 a
2 26 a
3 27 a
1 28 m2 23 m
1 36 p2 33 p
Now I want to transpose the rows present in this table to columns based on the flag, something like
CategoryId | aValue | mValue | PValue
1 25 28 36
2 26 23 33
3 27 null null
I am trying to join based on the category id but I am just getting the matched records (inner join) in my resultset even if I use left outer join in my query.
My query:
SELECT
A.CategoryId,
A.Value AS actual,
B.Value AS projected,
C.Value AS Manual
FROM ((a AS A left JOIN b AS B ON A.categoryid=B.categoryid)
left JOIN c AS C ON A.categoryid=C.categoryid)
WHERE (((A.flag)="a") and ((B.flag)="p") and ((C.flag) ="m"))
I am getting the proper results if I have the data in 3 different tables.
I just want to check what would be the best way to transpose a rows to column when using self join...
Thanks,
Barani

Try this:
SELECT CategoryId,
MIN(SWITCH(YourTable.Flag = 'a',Value)) AS aValue,
MIN(SWITCH(YourTable.Flag = 'm',Value)) AS mValue,
MIN(SWITCH(YourTable.Flag = 'p',Value)) AS pValue
FROM YourTable
GROUP BY CategoryId

Related

how to execute query for each row result of another query

I have 2 tables , one stores IDs and another logs for each ID , i would like to get sum of log for each ID and ID number from these 2 tables
A B
------- -------------
ID ID_C LOG
1 1 15
2 1 30
3 4 44
4 2 14
5 3 88
3 10
2 10
for getting sum query is
SELECT SUM(LOG) FROM B WHERE ID_C ='2' ;
notice ID and ID_C are same but name is different in tables
and for getting all ids available query is
SELECT ID FROM A ;
I would like to get the following table result
result
--------------------
ID SUM
1 45
4 44
2 24
3 98
I tried
SELECT SUM(LOG) FROM B WHERE ID_C in (SELECT ID FROM A ) ;
but it result in sum of all IDs
It looks like you just need a join aggregation here:
SELECT a.ID, SUM(b.LOG) AS SUM
FROM A a
INNER JOIN B b
ON b.ID_C = a.ID
GROUP BY a.ID
ORDER BY a.ID;
Note that the inner join will also remove ID values from the A table which no entries whatsoever in the B table, which seems to be the behavior you want.
you should use inner join and GROUP BY:
SELECT A.ID as ID, SUM(LOG) AS SumLOG
FROM A inner join B ON A.ID = B.ID_C
GROUP BY A.ID
if you needed can use where for ID filter.

Values from a table that are not in another one

I have two tables, A and B.
A
ID age
1 24
2 25
45 22
B
ID school
34 school1
1 school2
I want to select IDs that are in B but not in A.
I wrote
Select distinct bb.school
From B as bb
Left outer join A as aa
On bb.ID=aa.ID
inner join C as cc
On bb.school=cc.school
This code returns exactly the same number of rows that I would have with an inner join instead of left outer join.
Am I doing something wrong?
Try using not in;
Select * From A Where ID Not In ( Select ID From B )

full-join issue in SQL server

I have two tables total_sales_store :
store. total_sales
23 198750953.849999
29 77141561.3099999
9 77789512.9899997
15 89133935.9200002
3 57586980.0699998
32 166819624.16
26 143416610.79
12 144287538.149999
35 131520910.08
6 223756634.64
43 90565869.4100002
21 108118179.92
27 253856294.88
38 55159990.42
7 81598450.1399996
and storesdata:
store. type
1 A
2 A
3 B
4 A
5 B
6 A
7 B
8 A
9 B
10 B
11 A
I want to full join the two table so that I have this desired table:
store. Type. totalsales
1 A 123124
2 B 141221
3 C 134141
4 A. 234234
5 B 2323
6 C 123214
...
So I used the following query:
SELECT A.Store,a.total_sales
FROM totalsales_store A
FULL JOIN
(
SELECT [Type], Store
FROM storesdata
) B
ON A.Store = B.Store
ORDER BY total_sales DESC
But what I got is this:
[enter image description here][3]
which neglects the Type column. What can I do to make this work? Thank you!
With a FULL JOIN you will get all results from both tables, even when they don't match each other, so you should account for the NULL store values across tables. Otherwise simply include the Type column in the select.
I didn't see a need for a sub-query.
SELECT
ISNULL(A.Store, B.Store) Store,
B.Type,
a.total_sales
FROM
totalsales_store A
FULL JOIN storesdata B ON
A.Store = B.Store
ORDER BY
a.total_sales DESC
I suspect you can get away with
SELECT
A.Store,
B.Type,
a.total_sales
FROM
totalsales_store A
JOIN storesdata B ON
A.Store = B.Store
ORDER BY
a.total_sales DESC

comparing rows in sql on two different columns

id address retailer
1 A 11
2 A 11
3 A 11
4 A 12
5 A 13
6 B 12
7 B 12
8 B 13
My output should be
id address retailer
1 A 11
4 A 12
5 A 13
6 B 12
8 B 13
i.e my query should return id's which have same address but not same retailer.
How toget this?
Try to use group by clause as below:
select min(id), address, retailer
from tab
group by address, retailer
Assuming you're joining on columns with no duplicates, which is by far the most common case:
An inner join of A and B gives the result of A intersect B, i.e. the inner part of a venn diagram intersection.
An outer join of A and B gives the results of A union B, i.e. the outer parts of a venn diagram union.
Examples:
Suppose you have two Tables, with a single column each, and data as follows:
A B
- -
1 3
2 4
3 5
4 6
Note that (1,2) are unique to A, (3,4) are common, and (5,6) are unique to B.
Inner join:
An inner join using either of the equivalent queries gives the intersection of the two tables, i.e. the two rows they have in common.
select *
from a
INNER JOIN b on a.a = b.b;
select a.*,b.*
from a,b
where a.a = b.b;
a | b
--+--
3 | 3
4 | 4
Left outer join:
A left outer join will give all rows in A, plus any common rows in B.
select *
from a
LEFT OUTER JOIN b on a.a = b.b;
select a.*,b.*
from a,b
where a.a = b.b(+);
a | b
--+-----
1 | null
2 | null
3 | 3
4 | 4
Full outer join:
A full outer join will give you the union of A and B, i.e. All the rows in A and all the rows in B. If something in A doesn't have a corresponding datum in B, then the B portion is null, and vice versa.
select *
from a
FULL OUTER JOIN b on a.a = b.b;
a | b
-----+-----
1 | null
2 | null
3 | 3
4 | 4
null | 6
null | 5
select min(id) as id,address, retailer
from table1
group by address, retailer
order by id
The query you need is:
SELECT min(id), address, retailer
FROM table1 AS t1
group by address, retailer
order by address
Here's the source
Use This: It's working:
SELECT * FROM `sampletable` GROUP BY address, retailer

How to find difference of two columns using in Left Outer Join in SQL Sever 2005?

I have two Tables
Let suppose A and B
Now suppose the structure of table A is Like that
id stock
37 1
40 1
37 1
40 1
37 1
37 1
And B is like that
id stock
37 1
37 1
40 1
Now i want to write a query that give me sum of specific id stock in (table A - Table B) and if that id does not exist in table B then only stock from A.
So i will expect result like that
id stock
40 1
37 2
I thought that left join will be possible option here and i write query like that
SELECT A.id,
SUM(CAST(isNull(A.Stock, 0) as int) - CAST(isNull(B.Stock, 0) as int) )'Stock'
from A
LEFT OUTER JOIN
B
ON A.id = B.id
group by A.id
But Problem is that the above query gives desired records but wrong quantity/Stocklevel as shown below:
id stock
37 0
40 1
How can I resolve Stock Level issue.
I guess you are looking for something like this.
select A.id, A.SumA - coalesce(B.SumB, 0) as stock
from (
select A.id, sum(A.stock) as SumA
from A
group by A.id
) as A
left outer join
(
select B.id, sum(B.stock) as SumB
from B
group by B.id
) as B
on A.id = B.id
Result:
id stock
----------- -----------
37 2
40 1
SE Data
SELECT A.id, A.Stock - isNull(B.stock, 0) as Stock from A
LEFT OUTER JOIN B
ON A.id = B.id
That would be it I think.
PS. you group by something that you did not include in your case scenario. Your expected result is also not understandable to me (it conflicts with your problem description)