SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
C2 * C3 AS 'Total' --Invalid column name 'C2'.--
FROM TableA
How to reference C2 and C3, then do multiplication in that position ?
Any techniques ?
You can use inner-select:
SELECT *, C2 * C3 As Total
FROM (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
FROM TableA) DT;
or use a CTE like this:
;WITH t AS (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3,
FROM TableA)
SELECT *, C2 * C3 As Total
FROM t;
You can use with clause or a sub query.
;with tmp_tbl as (
SELECT
Answer_Code AS C0,
Text AS C1,
Price AS C2,
sum(case when Response like '%PAID%' then 1 else 0 end) AS C3
--C2 * C3 AS 'Total' --Invalid column name 'C2'.--
FROM TableA
)
select
C0,
C1,
C2,
C3,
C2 * C3 AS 'Total'
from tmp_tbl;
Related
I have a table like this:
C1 C2 C3 C4 C5 C6
INTERESES 40530 5 050405011232011 2013 5
PRINCIPAL 40529 5 050405011232011 2016 3
PRINCIPAL 40530 5 050405011232011 2013 4
And i need to group this rows by C1, C3 and C4 and return in the cases of lane 2 and 3 the C2 column with the max C5. I mean in this case this should return:
C1 C2 C3 C4 C5
INTERESES 40530 5 050405011232011 5
PRINCIPAL 40529 5 050405011232011 7
The second row should have 40529 in the column C2 cause it have the biggest value in the C5 column.
The C5 column should have the sum of the C6 of the previous table.
How can i do this? Thanks and sorry for my english
Instead of aggregation, one method uses window functions:
select c1, c2, c3, c4, sum_c5
from (select t.*,
sum(c5) over (partition by c1, c3, c4) as sum_c5,
row_number() over (partition by c1, c3, c4 order by c5 desc) as seqnum
from t
) t
where seqnum = 1;
Oracle also has keep syntax with allows you to get the "first" value in an aggregation:
select c1,
max(c2) keep (dense_rank first order by c5 desc) as c2,
c3, c4,
sum(c5)
from t
group by c1, c3, c4;
You can do it with NOT EXISTS:
select t.c1, t.c2, t.c3, t.c4
from tablename t
where not exists (
select 1 from tablename
where c1 = t.c1 and c2 = t.c2 and c3 = t.c3 and c5 > t.c5
)
Below is the sample table structure what I have got,
C1 C2 C3 C4
A D G X
B E H X
C F I X
select C2 as 1_C2, C3 as 1_C3 from table1 where C1 = A and C4=X
select C2 as 2_C2, C3 as 2_C3 from table1 where C1 = B and C4=X
select C2 as 3_C2, C3 as 3_C3 from table1 where C1 = C and C4=X
Above are the three select statements what I have got. Now I need to join all three select statements and get just one row as the output like,
1_C2 2_C2 3_C2 1_C3 2_C3 3_C3
D E F G H I
Saw multiple other posts but didn't match this requirement. Any help is highly appreciated.
You could use a CASE expression, combined with MAX():
select MAX(CASE WHEN C1 = 'A' THEN C2 END) as 1_C2,
MAX(CASE WHEN C1 = 'B' THEN C2 END) as 2_C2,
MAX(CASE WHEN C1 = 'C' THEN C2 END) as 3_C2,
MAX(CASE WHEN C1 = 'A' THEN C3 END) as 1_C3,
MAX(CASE WHEN C1 = 'B' THEN C3 END) as 2_C3,
MAX(CASE WHEN C1 = 'C' THEN C3 END) as 3_C3
from table1
where C1 in ('A', 'B', 'C')
and C4 = 'X';
The data I have is in the following format:
ID Category Gender Cost
1 C1 M 40
2 C2 F 50
3 C3 M 60
4 C1 F 40
5 C3 M 70
6 C3 F 50
.
.
.
and so on
Only C1, C2 and C3 exist as categories
The result I need is:
Category Male % Female % Avg. Cost
C1 0.5 0.5 40
C2 0 1 50
C3 0.6 0.4 60
What I have done in the stored procedure is I declared variables for C1 count, C2 count and C3 count, C1 female count, C2 female count, C3 female count, C1 Total Cost, C2 Total Cost, C3 Total cost, you get the idea. Then I calculated the average cost and male / female percentages.
It works but it's not a very elegant solution. I couldn't get the unpivot query to work so it gives me the result I need. Can this be done using unpivot or am I misunderstanding how pivots work? I tried something like this below but couldn't figure out how to include M/F percentage and average cost per category.
Thanks.
Something like this (which is incomplete):
Declare #TotalCount int;
SELECT #TotalCount = count(*) from MyTable;
SELECT Category, p.Total, CAST(p.Total * 1.0 / #TotalCount AS float) AS Percentage FROM --How to get F or M percentage, Average Cost Per Category , etc?
(
SELECT ISNULL(SUM(c.C1), 0) AS C1,
ISNULL(SUM(c.C2), 0) AS C2,
ISNULL(SUM(c.C3), 0) AS C3
FROM
(SELECT CASE WHEN Category = 'C1' THEN 1 ELSE 0 END AS C1,
CASE WHEN Category = 'C2' THEN 1 ELSE 0 END AS C2,
CASE WHEN Category = 'C3' THEN 1 ELSE 0 END AS C3
FROM #Candidates
) c --Do I need
) a
UNPIVOT
(
Total FOR Suitability IN (
C1,
C2,
C3
)
) p
Please check below query:
select
Category,
CAST(1.00*sum(case when Gender='M' then 1 else 0 end)/COUNT(Category) AS NUMERIC(18,1)) [Male %],
CAST(1.00*sum(case when Gender='F' then 1 else 0 end)/COUNT(Category) AS NUMERIC(18,1)) [Female %],
AVG(Cost) [Avg. Cost]
from tbl
group by Category
SQL Fiddle Demo
I want to combine two pieces of code into one, but I'm getting an error:
Part 1
SELECT idstd,namestd, idmajor,
c1, c2, c3, c4, c5, c6,
c7, c8, c9, c10,c11,c12,
c13,c14,c15
FROM
(SELECT status, idstd,namestd, idmajor,
'C' + cast(row_number()
OVER (partition BY idstd, idmajor
ORDER BY (SELECT 1)) AS varchar(10)) col
FROM tbcheked) src
PIVOT (MAX(status) FOR col IN (C1, C2, C3, C4, C5,
C6, C7, C8, C9, C10,
c11,c12,c13,c14,c15)) piv
This code is for checking if the column status has values of present, absent or leave.
Example:
id | c1 | c2 | c3 | c4 | c5 |
1 present absent present leave present
I have the second piece of code for status count:
SELECT idstd,
namemajor,
SUM(CASE WHEN status = 'present'
THEN 1
ELSE 0
END) AS present,
SUM(CASE WHEN status = 'absent'
THEN 1
ELSE 0
END) AS absent,
SUM(CASE WHEN status = 'leave'
THEN 1
ELSE 0
END) AS leave,
FROM tbcheked GROUP BY idstd, namemajor
ORDER BY idstd
Output:
id | present | absent | leave |
1 3 1 1
Now, I want to join both queries:
id | c1 | c2 | c3 | c4 | c5 | present | absent | leave |
1 present absent present leave present 3 1 1
Use join for conbining the output of both the queries.
select a.*, b.*
from (query 1)a join (query 2)b on a.id=b.id;
Treat each part as a sub-query and join them:
select
<whatever>
from
(
SELECT idstd,namestd, idmajor,
c1, c2, c3, c4, c5, c6,
c7, c8, c9, c10,c11,c12,
c13,c14,c15
FROM
(SELECT status, idstd,namestd, idmajor,
'C' + cast(row_number()
OVER (partition BY idstd, idmajor
ORDER BY (SELECT 1)) AS varchar(10)) col
FROM tbcheked) src
PIVOT (MAX(status) FOR col IN (C1, C2, C3, C4, C5,
C6, C7, C8, C9, C10,
c11,c12,c13,c14,c15)) piv
) as PivotedBit
INNER JOIN -- or OUTER, depending on your requirement
(
SELECT idstd,
namemajor,
SUM(CASE WHEN status = 'present'
THEN 1
ELSE 0
END) AS present,
SUM(CASE WHEN status = 'absent'
THEN 1
ELSE 0
END) AS absent,
SUM(CASE WHEN status = 'leave'
THEN 1
ELSE 0
END) AS leave,
FROM tbcheked GROUP BY idstd, namemajor
--ORDER BY idstd -- cannot have this in a sub-query
) as SummingBit
on SummingBit.idstd = PivotedBit.idstd
-- and any other common keys
ORDER BY idstd
It'll do two complete scans of tbcheked, so it won't be fast.
I have a hunch that adding dummy columns to the inner select of the PIVOT query using the CASE statements from the summing query, then adding SUM() to the PIVOT clause would be better. I haven't thought this through fully, however.
My base table is like:
ColumnA|ColumnB
---------------
A | C1
A | C2
A | C3
B | C1
B | C3
C | C4
I want to read records from the base table and write it into the below table:
ColumnA | C1 | C2 | C3 | C4
----------------------------
A | Y | Y | Y | N
B | Y | N | Y | N
C | N | N | N | Y
I don't want to use a cursor, but I don't know if that's possible or not.
Thanks
Have a look at the PIVOT command. From there you can do a INSERT INTO ... SELECT ...
SELECT ColumnA, [C1], [C2], [C3], [C4]
FROM (SELECT * FROM table) t
PIVOT
(
Count(ColumnB)
FOR ColumnB IN ([C1], [C2], [C3], [C4])
) As Pvt
One (usually fast) way would be group by:
insert NewTable (ColumnA, C1, C2, C3, C4)
select ColumnA
, IsNull(max(case when ColumnB = 'C1' then 'Y' end), 'N')
, IsNull(max(case when ColumnB = 'C2' then 'Y' end), 'N')
, IsNull(max(case when ColumnB = 'C3' then 'Y' end), 'N')
, IsNull(max(case when ColumnB = 'C4' then 'Y' end), 'N')
from OldTable
group by
ColumnA
Another way is subqueries, like:
insert NewTable (ColumnA, C1, C2, C3, C4)
select src.ColumnA
, case when exists (select * from OldTable ot
where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C1')
then 'Y' else 'N' end
, case when exists (select * from OldTable ot
where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C2')
then 'Y' else 'N' end
, case when exists (select * from OldTable ot
where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C3')
then 'Y' else 'N' end
, case when exists (select * from OldTable ot
where ot.ColumnA = src.ColumnA and ot.ColumnB = 'C4')
then 'Y' else 'N' end
from (
select distinct ColumnA
from OldTable
) src
Or, adapted from Chris Diver's answer, with pivot:
select ColumnA
, case when C1 > 0 then 'Y' else 'N' end C1
, case when C2 > 0 then 'Y' else 'N' end C2
, case when C3 > 0 then 'Y' else 'N' end C3
, case when C4 > 0 then 'Y' else 'N' end C4
from OldTable src
pivot (
count(ColumnB)
for ColumnB IN ([C1], [C2], [C3], [C4])
) pvt
assuming you can SELECT the information you like, then you can write the insert as the result of that selection.