How to combine columns in sql based on another field - sql

I have a table in SQL Server 2008 R2 like this:
Acc_id Bench-1 Bench-2
-------------------------------
1 xx
1 vv
2 pp
2 ii
3 kk
4 ll
Now, I want to combine this table on the basis of Acc_id column and get something like:
Acc_id Bench-1 Bench-2
---------------------------------
1 xx vv
2 pp ii
3 kk
4 ll
So, could someone please help me out.

SELECT ISNULL(b1.Acc_id,b2.Acc_id) as Acc_id,
b1.data,
b2.data
FROM Bench-1 AS b1 FULL OUTER JOIN
Bench-2 AS b2 ON b2.Acc_id = b1.Acc_id

Check Below query
SELECT DISTINCT a.acc_id,
b.bench_1,
c.bench_2
FROM table1 a
LEFT OUTER JOIN (SELECT acc_id,
bench_1
FROM table1
WHERE Isnull(bench_1, '') <> '') b
ON a.acc_id = b.acc_id
LEFT OUTER JOIN (SELECT acc_id,
bench_2
FROM table1
WHERE Isnull(bench_2, '') <> '') c
ON a.acc_id = c.acc_id

I would do this like:
select
Acc_id,
max([Bench-1)] as [Bench-1],
max(([Bench-2]) as [Bench-2]
from
myTable
group by
Acc_id
This assumes Acc_id won't have multiple rows with data in the same columns
If that is the case then your knowledge of the use of the results will come into play. I often will perform this more completely like
select
Acc_id,
min([Bench-1)] as [Bench-1Min],
max([Bench-1)] as [Bench-1Max],
Count([Bench-1)] as [Bench-1Count],
min([Bench-2)] as [Bench-2Min],
max([Bench-2)] as [Bench-2Max],
Count([Bench-2)] as [Bench-2Count],
from
myTable
group by
Acc_id
All this depends on the actual complexity of the real data and what you want to do with the results. If it IS actually as simple as you example the multi-join solution may work for you, but I often find that in more complex summarizations the group by solution give me results and performance I need.

Related

SQL Server. T-SQL. CASE IF EXISTS query

I have a classification table that looks like this:
ID CLASSIFICATION
__________________
A1 BOARD
A2 SURFBOARD
A3 SURF
Then I have a category table that looks like this
CATEGORY PARENT INDENT
____________________________________
SURF NULL 3
SURFBOARD SURF 2
BOARD SURFBOARD 1
I want to make a SQL query, that returns this:
INDENT3 INDENT2 INDENT1 ID
______________________________________
SURF NULL NULL A3
SURF SURFBOARD NULL A2
SURF SURFBOARD BOARD A1
Is it possible?. I'm not getting any ideas, seems like I need to loop through the classification table and find if there is indent1, indent2 and indent3. But not sure If I can put a script in a query, or if there is some kind of query I can do to achieve this. Something like
FOREACH CLASSIFICATION
CASE EXIST CATEGORY WITH IDENT1 INDENT 1 ELSE NULL AS IDENT1,
CASE EXIST CATEGORY WITH IDENT2 INDENT 2 ELSE NULL AS IDENT2,
CASE EXIST CATEGORY WITH IDENT1 INDENT 3 ELSE NULL AS IDENT3
If your hierarchy has a maximum of 3 levels a simpler query may be:
select cl.classification as indent3, null as indent2, null as indent1, id
from classification cl
join category ca on ca.category = cl.classification
where ca.indent = 3
union
select ca2.category, cl.classification, null as indent3, id
from classification cl
join category ca on ca.category = cl.classification
join category ca2 on ca.parent = ca2.category
where ca.indent = 2
union
select ca3.category as indent3, ca2.category as indent2, cl.classification as indent1, id
from classification cl
join category ca on ca.category = cl.classification
join category ca2 on ca.parent = ca2.category
join category ca3 on ca2.parent = ca3.category
where ca.indent = 1
If you have an indefinite number of parent/child levels you might be better to search "parent hierarchy with CTE" for a more complicated but flexible method.
Your logic is a bit hard to follow, but this should product the results that you specify:
select max(case when cl.indent = 3 then cl.category end) over () as indent3,
(case when cl.indent < 3
then max(case when cl.indent = 2 and then cl.category end) over ()
end) as indent2,
(case when cl.indent < 2
then max(case when cl.indent = 1 and then cl.category end) over ()
end) as indent1,
cl.id
from category ca join
classification cl
on ca.category = cl.category
People not so god with SQL will tell you to avoid this, SQL gurus consider to treat you as one of the pack.
It somewhat hard to understand your model but I gave it a shot.
Bit tip from the coach, if you need an id, use incremental numbers from the database, it's faster, allow god index and no risk of unexpected duplicates or truncation.
CREATE TABLE cs (id char(10), classification char(20));
CREATE TABLE ct (category char(20), parent char(20), indent int);
INSERT INTO cs VALUES
('A1','BOARD'),
('A2','SURFBOARD'),
('A3','SURF');
INSERT INTO ct VALUES
('SURF',null,3),
('SURFBOARD','SURF',2),
('BOARD','SURFBOARD',1);
select cs.id, ct1.category indent1,ct2.category indent2,ct3.category indent3 from ct ct1
left join ct ct2 on ct2.category = ct1.parent
left join ct ct3 on ct3.category = ct2.parent
left join cs on cs.classification = ct1.category
Link to the code on SQLFiddle

Horizontal To Vertical Sql Server

I'm stuck with a SQL query (SQL Server) that involves converting horizontal rows to vertical rows
Below is my Query that I am trying
SELECT P AS Amount_Rs
FROM (
Select (F1.D32-F1.D20) As Profit_For_The_Period ,F3.D2 as Current_Libilities,F5.D20 As Capital_Acount,
--M1.Name As Name,
F2.D20 AS Loan_Liabilities,F4.d1 As Opening_Diff --F2.D68 As Loan,
from Folio1 As F1
--inner Join Master1 As m1 on m1.Code like '101' or m1.Code Like '102' or m1.Code Like '106' or m1.Code Like '109' or m1.Code lIke '103'
--And m1.Code=102 And m1.Code=101)
inner Join Folio1 As F2 On (F2.MasterCode=F2.MasterCode)
inner Join Folio1 As F3 On (F3.MasterCode=F3.MasterCode)
inner Join Folio1 As F4 On (F4.MasterCode=F4.MasterCode)
inner Join Folio1 As F5 On (F5.MasterCode=F5.MasterCode)
Where F1.MasterCode=109
and F2.MasterCode =106
and F3.MasterCode=103
and F4.MasterCode=102
And F5.MasterCode=101
) p UNPIVOT
( p FOR value IN
( Profit_For_The_Period,Capital_Acount, Current_Libilities, Loan_Liabilities, Opening_Diff )
) AS unvpt
Current Output:
1 12392
2 0
3 0
4 4000
5 -200
Desired Output:
1 Capital Account 12392
2 Current Assets 0
3 Current Liabilities 0
4 Loans (Liability) 4000
5 Revenue Accounts -200
Thanks !!!
I think you are looking for a pivot. Use the CASE statement with a SUM or any aggregate function in the SELECT part and a group by in the where clause, that's how I use to put rows into columns in a query when I have to in MySQL. I don't know SQL Server but I think you can do quite the same.
your conditions below
F1.MasterCode=109
and F2.MasterCode =106
and F3.MasterCode=103
and F4.MasterCode=102
And F5.MasterCode=101
shouldn't be in the the where clause but with the case in the select part
example :
select whatever,
case when F2.MasterCode =106 then sum(column_name)
end case as column_alias, (other columns) from ...
hope this could help

T-SQL cursor or if or case when

I have this table:
Table_NAME_A:
quotid itration QStatus
--------------------------------
5329 1 Assigned
5329 2 Inreview
5329 3 sold
4329 1 sold
4329 2 sold
3214 1 assigned
3214 2 Inreview
Result output should look like this:
quotid itration QStatus
------------------------------
5329 3 sold
4329 2 sold
3214 2 Inreview
T-SQL query, so basically I want the data within "sold" status if not there then "inreview" if not there then "assigned" and also at the same time if "sold" or "inreview" or "assigned" has multiple iteration then i want the highest "iteration".
Please help me, thanks in advance :)
This is a prioritization query. One way to do this is with successive comparisons in a union all:
select a.*
from table_a a
where quote_status = 'sold'
union all
select a.*
from table_a a
where quote_status = 'Inreview' and
not exists (select 1 from table_a a2 where a2.quoteid = a.quoteid and a2.quotestatus = 'sold')
union all
select a.*
from table_a a
where quote_status = 'assigned' and
not exists (select 1
from table_a a2
where a2.quoteid = a.quoteid and a2.quotestatus in ('sold', 'Inreview')
);
For performance on a larger set of data, you would want an index on table_a(quoteid, quotestatus).
You want neither cursors nor if/then for this. Instead, you'll use a series of self-joins to get these results. I'll also use a CTE to simplify getting the max iteration at each step:
with StatusIterations As
(
SELECT quotID, MAX(itration) Iteration, QStatus
FROM table_NAME_A
GROUP BY quotID, QStats
)
select q.quotID, coalesce(sold.Iteration,rev.Iteration,asngd.Iteration) Iteration,
coalesce(sold.QStatus, rev.QStatus, asngd.QStatus) QStatus
from
--initial pass for list of quotes, to ensure every quote is included in the results
(select distinct quotID from table_NAME_A) q
--one additional pass for each possible status
left join StatusIterations sold on sold.quotID = q.quotID and sold.QStatus = 'sold'
left join StatusIterations rev on rev.quotID = q.quotID and rev.QStatus = 'Inreview'
left join StatusIterations asngd on asngd.quotID = q.quotID and asngd.QStatus = 'assigned'
If you have a table that equates a status with a numeric value, you can further improve on this:
Table: Status
QStatus Sequence
'Sold' 3
'Inreview' 2
'Assigned' 1
And the code becomes:
select t.quotID, MAX(t.itration) itration, t.QStatus
from
(
select t.quotID, MAX(s.Sequence) As Sequence
from table_NAME_A t
inner join Status s on s.QStatus = t.QStatus
group by t.quotID
) seq
inner join Status s on s.Sequence = seq.Sequence
inner join table_NAME_A t on t.quotID = seq.quotID and t.QStatus = s.QStatus
group by t.quoteID, t.QStatus
The above may look like complicated at first, but it can be faster and it will scale easily beyond three statuses without changing the code.

Tricky SQLite query, could use some assistance

I have a rather confusing SQLite query that I can't seem to quite wrap my brain around.
I have the following four tables:
Table "S"
sID (string/guid) | sNum (integer)
-----------------------------------
aaa-aaa 1
bbb-bbb 2
ccc-ccc 3
ddd-ddd 4
eee-eee 5
fff-fff 6
ggg-ggg 7
Table "T"
tID (string/guid) | ... other stuff
-----------------------------------
000
www
xxx
yyy
zzz
Table "S2TMap"
sID | tID
-------------------
aaa-aaa 000
bbb-bbb 000
ccc-ccc xxx
ddd-ddd yyy
eee-eee www
fff-fff 000
ggg-ggg 000
Table "temp"
oldID (string/guid) | newID (string/guid)
------------------------------------------
dont care fff-fff
dont care ggg-ggg
dont care zzz
What I need is to be able to get the MAX() sNum that exists in a specified "t" if the sID doesn't exist in the temp.NewID table.
For example, given the T '000', '000' has S 'aaa-aaa', 'bbb-bbb', 'fff-fff', and 'ggg-ggg' mapped to it. However, both 'fff-fff' and 'ggg-ggg' exist in the TEMP table, which means I need to only look at 'aaa-aaa' and 'bbb-bbb'. Thus, the statement would return "2".
How would I go about doing this?
I was thinking something along the lines of the following for selecting s that don't exist in the "temp" table, but I'm not sure how to get the max of the seat and only do it based on a specific 't'
SELECT s.sID, s.sNum FROM s WHERE NOT EXISTS ( SELECT newID from temp where tmp.newID = s.sID)
Thanks!
Give this a try:
select max(s.sNum) result from s2tmap st
join s on st.sId = s.sId
where st.tId = '000' and not exists (
select * from temp
where temp.newId = st.sId)
Here is the fiddle to play with.
Another option, probably less efficient would be:
select max(s.sNum) result from s2tmap st
join s on st.sId = s.sId
where st.tId = '000' and st.sId not in (
select newId from temp)
The following query should give you a list of Ts and their max sNums (as long as all exist in S and S2TMap):
SELECT t.tID, MAX(sNum)
FROM S s
JOIN S2TMap map on s.sID=map.sID
JOIN T t on map.tId=t.tID
LEFT JOIN temp tmp on s.sID=tmp.newID
WHERE tmp.newID IS NULL
You were close, you just had to join on S2TMap and then to T in order to restrict the result set to a given T.
SELECT MAX(s.sNum)
FROM s
INNER JOIN S2TMap m on m.sID = s.sID
INNER JOIN t on t.tID = m.tID
WHERE t.tID = '000'
AND NOT EXISTS (
SELECT newID FROM temp WHERE temp.newID = s.sID
)

How to do a subquery using the result obtained in the original query?

Here is the situation I have..I have to fetch all the associated cases for a given quoteId and this requires a join of 3 tables and I am able to come up with a query for that. Below is the sample : for brevity I have omitted some table name and used only Alias name.
SELECT distinct caseTable.CASEID, quoteHdrTable.Case_UID FROM
caseTable INNER JOIN quoteHdrTable ON
quoteHdrTable.Case_UID = caseTable.Case_UID WHERE quoteHdrTable.QUOTE_ID = '12345'.
Now for each CASE_UID that returns back, I also need to display its status from a different table. That has structure below.
STATUS_TABLE
CASE_UID STATUS
------------ -----------
123 Good
234 Bad.
345 {null}
In the end I want a result like
result
case_ID case_UID status
001 123 Good
Can we use subquery to do a 2nd SQL using the result(case_UID) from first..please provide pointers or a sample SQL statement.
FYI..using DB2 database
Thanks
Sandeep
SELECT distinct c.CASEID, q.Case_UID, s.status
FROM caseTable c
INNER JOIN quoteHdrTable q ON q.Case_UID = c.Case_UID
LEFT JOIN StatusTable s ON s.CASE_UID = q.CASE_UID
WHERE quoteHdrTable.QUOTE_ID = '12345'
Why not just add another JOIN?
SELECT distinct
caseTable.CASEID,
quoteHdrTable.Case_UID,
status.STATUS
FROM caseTable
INNER JOIN quoteHdrTable
ON quoteHdrTable.Case_UID = caseTable.Case_UID
INNER JOIN STATUS_TABLE status
ON quoteHdrTable.Case_UID = status.Case_UID
WHERE quoteHdrTable.QUOTE_ID = '12345'