How pivot a sum of values - sql

i have a question, How can i pivot an aggregation result to look like ..
I'm trying to pivot a simple aggregation using this query first:
select sync_action action, count(sync_action) total
FROM my_table
group by sync_action
and to pivot the table i'm using:
select * from (
select sync_action , count(sync_action) total
FROM my_table
group by sync_action )
pivot
(
count(sync_action)
for sync_action in ('delete','create')
)
;
and i don't know where is the error, because the result is:
the idea is have the same as the first image.
Can somebody help me?
Best regards

I would just use conditional aggregation:
select
sum(case when sync_action = 'delete' then total else 0 end) sum_delete,
sum(case when sync_action = 'create' then total else 0 end) sum_create
from mytable
where sync_action in ('delete', 'create')

You don't need to do group by, just do like
SELECT *
FROM mytable
pivot
( COUNT(sync_action)
FOR sync_action IN('delete','create')
);

In your query you need "SUM of total" instead of "Count of sync_action" in pivot section. Others are ok. If you use count, in your case you will always get 1.
select * from (
select sync_action , count(sync_action) total
FROM my_table
group by sync_action ) as p
pivot
(
sum(p.total)
for p.sync_action in ("delete","create")
)pt

I think you just want:
select sum(case when sync_action = 'delete' then 1 else 0 end) as delete,
sum(case when sync_action = 'create' then 1 else 0 end) as create
from my_table;
I don't see how pivot helps at all with what you want to do.

Related

SQL: Select within Select as subquery

I've got the following statement:
select
product_name as ShortestLength = (select top 1 product_name, len(fact_name) Value_Length
from table
order by Value_Length, fact_name ASC)
Which returns this output:
shortestlength
PS
I'd like to add this outcome to another select statement:
select
'Product' as Column_Name,
avg(case when product is null then 1.000 else 0 end) * 100 as PctMissing,
count(product) as TotalCount,
count(distinct product) as UniqueCount
from
table
so the result will be:
column_name
pctmissing
totalcount
uniquecount
shortestlength
Product
5.100
181186
15
PS
What should I add to my initial select statement?
You can use conditional aggregation:
select 'Product' as Column_Name,
avg(case when t.product is null then 1.000 else 0 end)*100 as PctMissing,
count(t.product) as TotalCount,
count(distinct t.product) as UniqueCount,
max(case when seqnum = 1 then product_name end) as shortest_length
from (select t.*,
row_number() over (order by len(fact_name), fact_name) as seqnum
from table t
) t
This assumes that the two table references are really the same table.
You can just use first query as subquery in place of a column in your select statement:
select
'Product' as Column_Name,
avg(case when product is null then 1.000 else 0 end)*100 as PctMissing,
count(product) as TotalCount,
count(distinct product) as UniqueCount,
(select top 1 product_name from table order by Value_Length, fact_name ASC) as ShortestLength
from table

how to do math on results from two querys

i have to results that came from each query
first query:
SELECT [xcv], COUNT( * ) AS Total
FROM [my_table]
GROUP BY [xcv]
second query:
SELECT [xcv], COUNT( * ) AS Total
FROM [my_table]
WHERE=[result]='ok'
GROUP BY [xcv]
what i want to do is to get the value of -> [ (first_query/second query) *100 ]
And i want results for each [xcv] in my table...
any idea how i can do it ?
thank you all
SELECT t1.[xcv],
(t1.total/t2.total)*100
FROM (SELECT [xcv],
COUNT( * ) AS Total
FROM [my_table]
GROUP BY
[xcv]
) t1 JOIN (
SELECT [xcv],
COUNT( * ) AS Total
FROM [my_table]
WHERE [result]='ok'
GROUP BY
[xcv]
) t2
ON t1.[xcv]=t2.[xcv]
I also removed the = sign from WHERE=[result]='ok' - I think you mistyped it in.
One query:
SELECT [xcv],
(SUM(CASE
WHEN [result] = 'ok'
THEN 1
ELSE 0
END
)/COUNT( * )
) * 100
FROM [my_table]
GROUP BY [xcv]

SQL - WHERE on new column

I've a table with 3 columns: Id, Price, Total.
I'm writing this sql statement:
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
ELSE ''
END AS NewColumnName
FROM Table
If I run this sql, I have no error. But if I add a Where, like this:
WHERE NewColumnName= '1' the server return an error: the name of column NewColumnName is not valid.
Please help me!
Thanks a lot!!
RM
Can you try this way?
select *
from (
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
ELSE ''
END AS NewColumnName
FROM Table
) x
where
NewColumnName= '1'
Try this,
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
END AS NewColumnName
FROM Table
WHERE CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
END = '1'
Generally use a subquery,
SELECT Id, Price, Total, NewColumnName
FROM (
SELECT
Id,
Price,
Total,
CASE
WHEN [Total] IS NULL THEN '0'
ELSE '1'
END [NewColumnName]
FROM
Table) [WithNew]
WHERE
NewColumnName = '1';
or in your case you could do,
SELECT
Id,
Price,
Total,
1 [NewColumnName]
FROM
Table
WHERE
Total IS NOT NULL;
USE [AdventureWorks2012]
WITH cte as (
SELECT [AddressID], [AddressLine1]
, CASE WHEN [City] = 'Bothell' THEN 1 ELSE 0 END AS [NewColumn]
FROM Person.Address )
SELECT * FROM CTE
WHERE [NewColumn] = 1
So yours would be re-written like this:
WITH cte as (
SELECT Id, Price, Total,
CASE WHEN [Total] IS NULL THEN '0'
WHEN [Total] IS NOT NULL '1'
ELSE ''
END AS NewColumnName
FROM Table)
SELECT * FROM CTE where [NewColumnName] = 1
You can't use NewColumnName in the WHERE Clause. You will have to use the CASE statement again in WHERE Clause or do what #Lajos suggested.
You can just write your query like this:
SELECT Id, Price, Total,
FROM Table
WHERE Total IS NOT NULL
That's doing the same thing, except without the case statement.

Merge two SELECT queries into one

I have two queries where I only need the count of total records but the only difference in the queries is one field value.
Example;
SELECT COUNT(*) AS group_a
FROM tbl
WHERE category = 'value_a'
SELECT COUNT(*) AS group_b
FROM tbl
WHERE category = 'value_b'
How can I get something like this: (pseudo)
SELECT COUNT(*) AS group_a, COUNT(*) AS group_b
FROM tbl
WHERE category IN ('value_a', 'value_b')
But the results are like this
group_a , group_b
56, 101
I was thinking a CASE statement in the query to filter the two but how do I implement it? or is there a better way?
I'm doing a UNION right now but wanted to know if I could return one record with two results
select sum(case when category = 'value_a' then 1 else 0 end) as group_a,
sum(case when category = 'value_b' then 1 else 0 end) as group_b
from tbl
where category in ('value_a', 'value_b')
select sum(case when category = 'value_a' then 1 else 0 end) group_a,
sum(case when category = 'value_b' then 1 else 0 end) group_b
from tbl
SELECT category,COUNT(*) FROM tbl
GROUP BY category;
That expands to more categories. If you want just those categories
SELECT category,COUNT(*) FROM tbl
WHERE category IN ('value_a', 'value_b')
GROUP BY category;
What strange answers for counting. Here's a straightforward COUNT:
SELECT COUNT(category = 'value_a' OR NULL) AS group_a, COUNT(category = 'value_b' OR NULL) AS group_b FROM tbl;
The COUNT aggregate in PostgreSQL allows complex syntax like I've shown. Note that the OR NULL is quite essential as COUNT counts only those rows for which the condition category = '...' OR NULL gives non-NULL answer.
Just for the fun of it:
SELECT *
FROM
(
SELECT category
FROM tbl
) subquery
PIVOT
(
COUNT(category)
FOR category IN ([value_a],[value_b])
) AS piv

SQL Select for multiple where clause

I am trying to create SQL Select that returns counts of a certain field based on a field.
So, here is what I am trying to do.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct id where type='A') as TotalA, -- this will be total when type='A'
count(distinct id where type='B') as TotalB -- This will be total when type = 'B'
from MyTable
Basically, TotalCount = TotalA + TotalB.
How can I achieve this in SQL Select Statement?
Thanks.
Select count(distinct id) as TotalCount, -- this will be the total of id
count(distinct case type when 'A' then id else NULL end) as TotalA,
count(distinct case type when 'B' then id else NULL end) as TotalB
from MyTable;
Of course TotalCount may or may not be TotalA + TotalB, depending on the actual data.
You can do it like that:
SELECT
count(distinct id) as TotalCount,
sum(CASE WHEN type = 'A' THEN 1 ELSE 0) as TotalA,
sum(CASE WHEN type = 'B' THEN 1 ELSE 0) as TotalB,
FROM
MyTable
Count per type:
SELECT
type,
count(DISTINCT id)
FROM
MyTable
GROUP BY
type
Why not simply UNION the separate queries.
Select 'all' as which, count(distinct id) as Total from mytable
union
select 'a' as which, count(distinct id) where type='A' as Total from mytable
union
select 'b' as which, count(distinct id) where type='B' as Total from mytable