Counting instances of value in postgres query - sql

Bit of an SQL newbie question..
If I have a table along the lines of the following :
host fault fatal groupname
Host A Data smells iffy n research
Host B Flanklecrumpet needs a cuddle y production
Host A RAM loves EWE n research
Host Z One of the crossbeams gone askew on the treadle y research
.. and I want to get some stats, I can..
select count(distinct host) as hosts, count(host) as faults, group from tablename group by groupname
.. which gives me the number of faults and affected hosts per groupname.
hosts faults groupname
2 3 research
1 1 production
Can I, in the same query, show the number of fatal entries?

I would use aggregation, but in Postgres would phrase this as:
select groupname, count(distinct host) as hosts,
count(*) as num_faults,
count(*) filter (where fatal = 'Y') as num_fatal
from t
group by groupname;

use conditional aggregation
select count(distinct host) as hosts,
count(host) as faults,sum(case when fatal='y' then 1 else 0 end) as numberofenty,
groupname from tablename group by groupname

Related

SQL select column group by where the ratio of a value is 1

I am using PSQL.
I have a table with a few columns, one column is event that can have 4 different values - X1, X2, Y1, Y2. I have another column that is the name of the service and I want to group by using this column.
My goal is to make a query that take an event and verify that for a specific service name I have count(X1) == count(X2) if not display a new column with "error"
Is this even possible? I am kinda new to SQL and not sure how to write this.
So far I tried something like this
select
service_name, event, count(service_name)
from
service_table st
group by
(service_name, event);
I am getting the count of each event for specific service_name but I would like to verify that count of event 1 == count of event 2 for each service_name.
I want to add that each service_name have a choice of 2 different event only.
You may not need a subquery/CTE for this, but it will work (and makes the logic easier to follow):
WITH event_counts_by_service AS (SELECT
service_name
, COUNT(CASE WHEN event='X1' THEN 1 END) AS count_x1
, COUNT(CASE WHEN event='X2' THEN 1 END) AS count_x2
FROM service_table
GROUP BY service_name)
SELECT service_name
, CASE WHEN count_x1=count_x2 THEN NULL ELSE 'Error' END AS are_counts_equal
FROM event_counts_by_service

Oracle SQL: manipulating group

I have a simple query such as this
select duration, host from Jobs
group by host;
i want it actually group by a pool of hosts which is something that needs to be defined at query time
for example, host01-10 would be pool1, host11-20 would be pool2, etc.
at the moment, there isnt a field which says what pool it is in and but it needs to be derived from the host field.
how do i achieve that? I want to be able to creation some sort of function on the slide to maniuplate the field so that it is group-able
def get_pool(host):
if get_hostnumber(host) < 10:
return 'pool1'
elif:
...
select duration, get_pool(host) from Jobs
group by get_pool(host);
In SQL, you don't need a function for this. I would suggest just using a case expression:
select (case when host <= 'host10' then 'pool1'
when host <= 'host20' then 'pool2'
. . .
end) as hostgrp, sum(duration) as duration
from jobs
group by (case when host <= 'host10' then 'pool1'
when host <= 'host20' then 'pool2'
. . .
end);
For your particular example, you could get away with:
select 'pool' || floor( (cast(substr(host, 5, 6) as number) + 1) / 10),
sum(duration) as duration
from jobs
group by 'pool' || floor( (cast(substr(host, 5, 6) as number) + 1) / 10);
And, lest I forget, I you have a permanent mapping between hosts and their groups, then you should put a hosts reference table in the database and have a second column for the group. Then this query would simply use a join, and any other query you write would have the same information.
You can use case when in select and in group by:
select duration, (case when host <10 then 'pool1' when host between 10 and 19 then 'pool2')
from Jobs
group by (case when host <10 then 'pool1' when host between 10 and 19 then 'pool2');

Terminology for Query to group and find difference of number greater than 3?

Hello everyone I am an SQL noob and can't figure this out and not sure what I need to look for terminology wise to figure it out so even just the proper terms to research would be of great help.
That said, here is the table I need to query:
Port Table
With that table I need to be able to find out which countries have more than two ports and which of those ports have a difference of more than 3 docks.
The data should be formatted to look like this:
Final Query Format
For your first question, which countries have more than two ports, you can use like
SELECT COUNTRY FROM TABLENAME GROUP BY COUNTRY HAVING COUNT(PORTNAME) > 2
now with this result, you have to find "which of those ports have a difference of more than 3 docks."
so, you can write like
SELECT A.PORTNAME AS FIRSTPORT, A.NUMDOCKS AS FIRSTNUM,
B.PORTNAME AS SECONDPORT, B.NUMDOCKS AS SECONDOCKS,
A.COUNTRY
FROM TABLENAME AS A,
TABLENAME AS B,
(SELECT COUNTRY FROM TABLENAME GROUP BY COUNTRY HAVING COUNT(PORTNAME) > 2) AS C
WHERE A.COUNTRY = C.COUNTRY
AND B.COUNTRY = C.COUNTRY
AND 3 < (A.NUMDOCKS - B.NUMDOCKS)

Cypher - Issue with Where + Aggregate + With

I am trying to execute the following Cypher query
START b=node:customer_idx(ID = 'ABCD')
MATCH p = b-[r1:LIKES]->stuff, someone_else_too-[r2:LIKES]->stuff
with b,someone_else_too, count(*) as matchingstuffcount
where matchingstuffcount > 1
//with b, someone_else_too, matchingstuffcount, CASE WHEN ...that has r1, r2... END as SortIndex
return someone_else_too, SortIndex
order by SortIndex
The above query works fine but moment I uncomment lower "with" I get following errors
Unknown identifier `b`.
Unknown identifier `someone_else_too`.
Unknown identifier `matchingstuffcount`.
Unknown identifier `r1`.
Unknown identifier `r2`.
To get around, I include r1 and r2 in the top with - "with b,someone_else_too, count(*) as matchingstuffcount". to "with b, r1, r2, someone_else_too, count(*) as matchingstuffcount". This messes my count(*) > 1 condition as count(*) does not aggregate properly.
Any workarounds / suggestions to filter out count(*) > 1 while making sure Case When can also be executed ?
Under neo4j 2.0 via console.neo4j.org I was able to get the following query to work. I tried to mimic the constructs you had, namely the WITH/WHERE/WITH/RETURN sequence. (If I missed something, please let me know!)
START n=node:node_auto_index(name='Neo')
MATCH n-[r:KNOWS|LOVES*]->m
WITH n,COUNT(r) AS cnt,m
WHERE cnt >1
WITH n, cnt, m, CASE WHEN m.name?='Cypher' THEN 1 ELSE 0 END AS isCypher
RETURN n AS Neo, cnt, m, isCypher
ORDER BY cnt
Update it or change it here.

Trouble with oracle sql query

I am trying to make a query of
"What are the names of the producers
with at least 2 properties with areas
with less than 10"
I have made the following query that seems to work:
select Producers.name
from Producers
where (
select count(Properties.prop_id)
from Properties
where Properties.area < 10 and Properties.owner = Properties.nif
) >= 2;
yet, my lecturer was not very happy about it. He even thought (at least gave me the impression of) that this kind of queries wouldn't be valid in oracle.
How should one make this query, then? (I have at the moment no way of getting to speak with him btw).
Here are the tables:
Producer (nif (pk), name, ...)
Property (area, owner (fk to
producer), area, ... )
The having clause is typically used to filter on aggregate data (like counts, sums, max, etc).
select
producers.name,
count(*)
from
producers,
property
where
producers.nif = property.owner and
property.area < 10
group by
producers.name
having
count(*) >= 2
select P.name
from Producers p, Properties pr
where p.nif = pr.Owner
AND Properties.area < 10
GROUP BY Producers.name
having Count(*) >= 2