How to formulate a conditional sum in PostgreSQL? - sql

I have a table containing id, category, noofquestions and company. I want a query which would return the noofquestions as sum of the values of noofquestions when category is same in two or more columns. I'm trying this query but it is only adding those columns whose category is same and noofquestions are equal which is wrong. It should not check for noofquestions.
SELECT id , category, SUM(NULLIF(noofquestions, '')::int), company
FROM tableName
WHERE id=1
GROUP BY id, category, noofquestions, company;

You should not group by noofquestions:
SELECT id, category, SUM(NULLIF(noofquestions, '')::int), company
FROM tableName
WHERE id = 1
GROUP BY id, category, company;

Related

SELECT DISTINCT doesn't appear to work with big query

I am filtering to a second created table that have duplicates removed. However I'm finding that DISTINCT seems not be working, and I end up with rows with identical ids. I want to only select one unique ID and throw any remaining ones away, but this is not what is happening. In other-words I do not care about the other column names.
def de_dupe_affiliates(read_table, write_table):
query = """
CREATE OR REPLACE TABLE `{write_table}` AS
SELECT DISTINCT ID, BRAND, TITLE, SHORT_TITLE, PRICE, FROM `{read_table}`
""".format(read_table=read_table,write_table=write_table)
response = client.query(query).result()
I also tried
SELECT DISTINCT(ID), BRAND
But this did the same. Is it possible to do this with a DISTINCT on one column?
Consider below approach
SELECT AS VALUE ANY_VALUE(t) FROM (
SELECT ID, BRAND, TITLE, SHORT_TITLE, PRICE FROM read_table
) t
GROUP BY ID
Your select clause
SELECT DISTINCT ID, BRAND, TITLE, SHORT_TITLE, PRICE FROM `{read_table}`
is equivalent to
SELECT ID, BRAND, TITLE, SHORT_TITLE, PRICE FROM `{read_table}` GROUP BY ID, BRAND, TITLE, SHORT_TITLE, PRICE
meaning any differences within these fields creates new rows in your result.
Your query works only if ID, BRAND, TITLE, SHORT_TITLE, PRICE fields are unique.
If not, you may use window functions like row_number() or rank() to select one row per id.

Filter by number of occurrences in a SQL Table

Given the following table where the Name value might be repeated in multiple rows:
How can we determine how many times a Name value exists in the table and can we filter on names that have a specific number of occurrances.
For instance, how can I filter this table to show only names that appear twice?
You can use group by and having to exhibit names that appear twice in the table:
select name, count(*) cnt
from mytable
group by name
having count(*) = 2
Then if you want the overall count of names that appear twice, you can add another level of aggregation:
select count(*) cnt
from (
select name
from mytable
group by name
having count(*) = 2
) t
It sounds like you're looking for a histogram of the frequency of name counts. Something like this
with counts_cte(name, cnt) as (
select name, count(*)
from mytable
group by name)
select cnt, count(*) num_names
from counts_cte
group by cnt
order by 2 desc;
You need to use a GROUP BY clause to find counts of name repeated as
select name, count(*) AS Repeated
from Your_Table_Name
group by name;
If You want to show only those Which are repeated more than one times. Then use the below query which will show those occurrences which are there more than one times.
select name, count(*) AS Repeated
from Your_Table_Name
group by name having count(*) > 1;

count duplicates and non duplicates

Using MS Access SQL
Is it possible to;
list and count all duplicates in one field based on another field?
list all non duplicates in one field based on another field?
Example database below
Based on your results, you just want a simple group by:
select name, year, count(*)
from [table]
group by name, year;
One statement cannot return two different headers. I mean, you could run two queries:
select name, year, count(*) as NumDuplicates
from [table]
group by name, year
having count(*) > 1;
select name, year, count(*) as NumNonDuplicates
from [table]
group by name, year
having count(*) = 1;

select max, min values from two tables

I have two tables. Differ in that an archive is a table and the other holds the current record. These are the tables recording sales in the company. In both we have among other fields: id, name, price of sale. I need to select from both tables, the highest and lowest price for a given name. I tried to do with the query:
select name, max (price_of_sale), min (price_of_sale)
from wapzby
union
select name, max (price_of_sale), min (price_of_sale)
from wpzby
order by name
but such an inquiry draws me two records - one of the current table, one table archival. I want to chose a name for the smallest and the largest price immediately from both tables. How do I get this query?
Here's two options (MSSql compliant)
Note: UNION ALL will combine the sets without eliminating duplicates. That's a much simpler behavior than UNION.
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM
(
SELECT Name, Price_Of_Sale
FROM wapzby
UNION ALL
SELECT Name, Price_Of_Sale
FROM wpzby
) as subQuery
GROUP BY Name
ORDER BY Name
This one figures out the max and min from each table before combining the set - it may be more performant to do it this way.
SELECT Name, MAX(MaxPrice) as MaxPrice, MIN(MinPrice) as MinPrice
FROM
(
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM wapzby
GROUP BY Name
UNION ALL
SELECT Name, MAX(Price_Of_Sale) as MaxPrice, MIN(Price_Of_Sale) as MinPrice
FROM wpzby
GROUP BY Name
) as subQuery
GROUP BY Name
ORDER BY Name
In SQL Server you could use a subquery:
SELECT [name],
MAX([price_of_sale]) AS [MAX price_of_sale],
MIN([price_of_sale]) AS [MIN price_of_sale]
FROM (
SELECT [name],
[price_of_sale]
FROM [dbo].[wapzby]
UNION
SELECT [name],
[price_of_sale]
FROM [dbo].[wpzby]
) u
GROUP BY [name]
ORDER BY [name]
Is this more like what you want?
SELECT
a.name,
MAX (a.price_of_sale),
MIN (a.price_of_sale) ,
b.name,
MAX (b.price_of_sale),
MIN (b.price_of_sale)
FROM
wapzby a,
wpzby b
ORDER BY
a.name
It's untested but should return all your records on one row without the need for a union
SELECT MAX(value) FROM tabl1 UNION SELECT MAX(value) FROM tabl2;
SELECT MIN(value) FROM tabl1 UNION SELECT MIN(value) FROM tabl2;
SELECT (SELECT MAX(value) FROM table1 WHERE trn_type='CSL' and till='TILL01') as summ, (SELECT MAX(value) FROM table2WHERE trn_type='CSL' and till='TILL01') as summ_hist

Aggregate SQL Function to grab only one from each grouping

I have a table that I need to normalize with many fields In SQL-Server 2000.
It contains 2 fields which I'm using to come up with distinct combination as defined by the specs.
ID and Rate: there are multiple rows of same IDs and Rates
I first created a temp table by grouping the IDs and Rates combination.
SELECT ID, Count(*) AS IDCounts, SUM(RATE) As Total
INTO #Temp
GROUP BY ID
Now I use Distinct to find only the unique combinations. So i'll have multiple ID groups sharing same Total and IDCounts
SELECT DISTINCT Total, IDCounts
INTO #uniques
FROM #Temp
Now my question is how to join a single ID back to that distinct grouping of IDCounts and Total and put that into a new table? It doesn't matter which one of the IDs in the groups as long as I use one from the same grouping.
Keeping your temp tables (although this could all be done in a single query):
SELECT ID, Count(*) AS IDCounts, SUM(RATE) As Total
INTO #Temp
GROUP BY ID
SELECT Total, IDCounts, MIN(ID) AS SomeID
INTO #uniques
FROM #Temp
GROUP BY Total, IDCounts
Add "Min(ID) AS FirstID" to the select into #uniques.
Try something like this:
SELECT MAX(ID) AS Id, Count(*) AS IDCounts, SUM(RATE) As Total
FROM SOMETABLE
GROUP BY IDCounts, Total