SQL counting total rows with distinct? - sql

i need a complex query:
Consider this table:
ID - field1 - field2
=================
1 a 10
2 a 10
3 a 20
4 b 20
i need a query that counts the total record grouped by field1 and field2. I mean i need this result:
field - count
==================
field1 a - 3
field1 b - 1
field2 10 - 2
field2 20 - 2
maybe i need to do 2 query for each field i need the count?
SELECT field1, COUNT( * ) FROM t1 GROUP BY field1
?
Thanks for any suggestions

You do need two SELECTs, but you can get them to return a single result set as follows. Note that you need to CAST the first SELECT so that the values are compatible with the text field in the second SELECT:
SELECT 'field1' AS FieldName, CAST(field1 AS CHAR) AS FieldValue, COUNT(*) AS Count
FROM table GROUP BY field1
UNION ALL
SELECT 'field2' AS FieldName, field2 AS FieldValue, COUNT(*) AS Count
FROM table GROUP BY field2

Related

Select unique field1 that has >1 distinct instances of field2 associated with it?

How can I query for the distinct field1 instances that have multiple distinct corresponding field2 values?
field1
field2
a
apple
b
grape
c
banana
b
orange
a
apple
In this example I want to return "b", since there are at least 2 distinct values (grape and orange) for field2 that correspond to it. I don't wan't "a" since there is only 1 unique field2 value that corresponds, "apple".
I have tried
with all_unique_combos as (
select distinct field1, field2
from table
)
select field1
from all_unique_combos
group by field1
having count(field2) > 1
I actually think this is right and would give me what I need. But at the moment it's returning 0 rows so I kinda need a sanity check. Thanks for any input either way.
You can use aggregation:
select field1
from t
group by field1
having min(field2) <> max(field2);
A straight-forward approach uses group by and having:
select field1
from mytable
group by field1
having min(field2) <> max(field2)
Using COUNT(DISTINCT ...):
select field1
from tab
group by field1
having count(disitnct field2) > 1

sql - getting sum of same column from multiple tables

I have a few tables in my DB. Let's call them table1, table2, table3.
All of them have a column named value.
I need to create a query that will return a single number, where this number is the sum of all the value columns from all the tables together...
I've tried the following way:
SELECT (SELECT SUM(value) FROM table1) + (SELECT SUM(value) FROM table2) + (SELECT SUM(value) FROM table3) as total_sum
But when at least one of the inner SUM is NULL, the entire total value (total_sum here) is NULL, so that's not very trustworthy.
When there is no value in a certain inner SUM query, I need it to return 0, so it doesn't affect the rest of the SUM.
To make it more clear, let's say I have the following 2 tables:
TABLE1:
ID | NAME | VALUE
1 Name1 1000
2 Name2 2000
3 Name3 3000
TABLE2:
ID | NAME | VALUE
1 Name1 1500
2 Name2 2500
3 Name3 3500
Eventually, the query I need will return a single value - 13500, which is the total sum of all the values under the VALUE column of all the tables here.
All the other columns have no meaning for the needed query, and I even don't care much for performance in this case.
You can achieve it using Coalesce as follows
SELECT
(SELECT coalesce(SUM(value),0) FROM table1) +
(SELECT coalesce(SUM(value),0) FROM table2) +
(SELECT coalesce(SUM(value),0) FROM table3) as total_sum
Another approach is to use union all to merge all values into single table
select distinct coalesce(sum(a.value), 0) as total_sum from
(select value from table1
union all
select value from table 2
union all
select value from table 3) a;
You can use the ISNULL function to take care of the NULLs.
SELECT ISNULL((
SELECT SUM(value) FROM table1
)
, 0
) + ISNULL((
SELECT SUM(value) FROM table2
)
, 0
) + ISNULL((
SELECT SUM(value) FROM table3
)
, 0
) AS total_sum;
You could simply sum all of them:
select sum(total) as Total
from (
select sum(value) as total from Table1
union all
select sum(value) as total from Table2
union all
select sum(value) as total from Table3
) t;

How to pivot a single row summary in postgresql

SQLFiddle here: http://sqlfiddle.com/#!15/e8e49/2/0
I want to get some summary data from my table into rows instead of columns..
select
sum(n),
avg(n),
max(n),
min(n)
from Table1
this returns a single row, multi-column result.
How can I get it into a result that's something like this:
Label | Res
-------------
min | 2
max | 3
count | 30
... etc ...
Postgres does not have a pivot trasformation...
select
'sum' as "key",sum(n) as "value" from Table1
union all
select 'avg', avg(n) from Table1
union all
select 'max', max(n) from Table1
union all
select 'min', min(n) from Table1
or if you have superuser can try CREATE EXTENSION tablefunc

Inserting a unique int into a non primary key field

I'm trying to make an SQL query using INSERT INTO to copy a number of rows from a table, but I want one of the fields (which isn't a primary key) to have a new, unique, int (I know this is terrible database design, but I can't change the structure of the DB).
Here is a simplified example of what I'm trying to do:
INSERT INTO Mytable
(field1
,field2
,field3
,nonKeyUniqueInt)
SELECT
(field1
,field2
,field3
,(SELECT MAX(nonKeyUniqueInt)+1 FROM mytable)
FROM
mytable
WHERE
(conditions)
However this doesn't work because the SELECT MAX query only runs once, giving all my new rows the same value for that field. Given the following rows to copy:
field1 field2 field3 nonKeyUniqueInt
x y z 1
a b c 2
I get output of:
field1 field2 field3 nonKeyUniqueInt
x y z 1
a b c 2
x y z 3
a b c 3
Is what I'm trying to do possible?
The problem is that the subquery gets evaluated once for the insert, not once per row. The solution is to use row_number():
INSERT INTO Mytable(field1, field2, field3, nonKeyUniqueInt)
SELECT field1, field2, field3,
x.maxk + row_number() over (order by (select NULL))
FROM mytable CROSS JOIN
(SELECT MAX(nonKeyUniqueInt) as maxk FROM mytable) x
WHERE (conditions);
I moved the max calculation to the FROM clause to make it clear that it is evaluated only once.

Fetching multiple rows based on grouping

Consider this data
PK field1 field2
1 a b
2 a (null)
3 x y
4 x z
5 q w
I need to get this data
select all columns from all rows where field1 has count >1
Which means the desired output is
PK field1 field2
1 a b
2 a (null)
3 x y
4 x z
i tried and finally settled for
select * from mytable where field1 in
(select field1 from mytable group by field1 having count(field1)>1 ) order by field1
but there has to be a better way than this
That's the way I would do it.
You could rewrite it with a join to the subquery instead of using in, but I doubt it would be any faster.
Edit: Ok, so for reference, the "join" method would go something like this:
select m.* from mytable m
join (
select field1 from mytable
group by field1
having count(field1)>1
) j on m.field1=j.field1
order by m.field1
And it seems it's worth testing to see if it's faster (thanks #binaryLV).
Another way, if using T-SQL
;WITH T AS
(
SELECT PK, FIELD1, FIELD2, COUNT(FIELD1) OVER(PARTITION BY FIELD1) AS R
)
SELECT PK, FIELD1, FIELD2
FROM T
WHERE R > 1