Error in getting the value from the database table - sql

I've sorted out people who got full score for the challenge of different difficulty level. However, the question states that query hacker_id and name of the people who got full score for more than once. I'm encountering a problem with COUNT. I tried to count the frequency of the name appearing in the table, but it wouldn't allow me to. I suspect there is something wrong with the GROUPBY syntax. Could anybody help me?
Previous Code
Select s.challenge_id,s.hacker_id,h.name,s.submission_id,c.difficulty_level,s.score
FROM (((Hackers AS h JOIN Submission AS s ON h.hacker_id=s.hacker_id)JOIN Challenges AS c ON c.challenge_id=s.challenge_id)JOIN Difficulty AS d ON d.difficulty_level=c.difficulty_level)
WHERE c.difficulty_level=d.difficulty_level and s.score=d.score
Result
challenge_id | hacker_id | name |submission_id |difficulty_level |score
71055 86870 Todd 94613 2 30
66730 90411 Joe 97397 6 100
71055 90411 Joe 97431 2 30
Problem
Select g.hacker_id,g.name,COUNT(g.name)
FROM (Select s.challenge_id,s.hacker_id,h.name,s.submission_id,c.difficulty_level,s.score
FROM (((Hackers AS h JOIN Submission AS s ON h.hacker_id=s.hacker_id)JOIN Challenges AS c ON c.challenge_id=s.challenge_id)JOIN Difficulty AS d ON d.difficulty_level=c.difficulty_level)
WHERE c.difficulty_level=d.difficulty_level and s.score=d.score) AS g
WHERE COUNT(g.name)>1
GROUBY g.hacker_id,g.name;

If you need COUNT of each name that appeared more than once in your first query then you can use the following
SELECT hacker_id, name, COUNT(name)
FROM
(
Select s.challenge_id,s.hacker_id,h.name,s.submission_id,c.difficulty_level,s.score
FROM (((Hackers AS h JOIN Submission AS s ON h.hacker_id=s.hacker_id)JOIN Challenges AS c ON c.challenge_id=s.challenge_id)JOIN Difficulty AS d ON d.difficulty_level=c.difficulty_level)
WHERE c.difficulty_level=d.difficulty_level and s.score=d.score
) AS T
GROUP BY hacker_id, name
HAVING COUNT(name) > 1
HAVING is used to filter the aggregated result

Related

Count the number of occurences in each bucket Redshift SQL

This might be difficult to explain. But Im trying to write a redshift sql query where I have want the count of organizations that fall into different market buckets. There are 50 markets. For example company x can be only be found in 1 market and company y can be found in 3 markets. I want to preface that I have over 10,000 companies to fit into these buckets. So ideally it would be more like, hypothetically 500 companies are found in 3 markets or 7 companies are found in 50 markets.
The table would like
Market Bucket
Org Count
1 Markets
3
2 Markets
1
3 Markets
0
select count(distinct case when enterprise_account = true and (market_name then organization_id end) as "1 Market" from organization_facts
I was trying to formulate the query from above but I got confused on how to effectively formulate the query
Organization Facts
Market Name
Org ID
Org Name
New York
15683
Company x
Orlando
38478
Company y
Twin Cities
2738
Company z
Twin Cities
15683
Company x
Detroit
99
Company xy
You would need a sub-query that retrieves the number of markets per company, and an outer query that summarises into a count of markets.
Something like:
with markets as (
select
org_name,
count(distinct market_name) as market_count
from organization_facts
)
select
market_count,
count(*) as org_count
from markets
group by market_count
order by market_count
If I follow you correctly, you can do this with two levels of aggregation. Assuming that org_id represents a company in your dataset:
select cnt_markets, count(*) cnt_org_id
from (select count(*) cnt_markets from organization_facts group by org_id) t
group by cnt_markets
The subquery counts the number of markets per company. I assumed no duplicate (ord_id, market_name) tuples in the table ; if that's not the case, then you need count(distinct market_name) instead of count(*) in that spot.
Then, the outer query just counts how many times each market count occurs in the subquery, which yields the result that you want.
Note that I left apart the enterprise_account column ,that appears in your query but not in your data.

Oracle SQL Count function

I am hoping someone can advise on the below please?
I have some code (below), it is pulling the data I need with no issues. I have been trying (in vain) to add a COUNT function in here somewhere. The output I am looking for would be a count of how many orders are assigned to each agent. I tried a few diffent things based on other questions but can't seem to get it correct. I think I am placing the COUNT 'Agent' statement and the GROUP BY in the wrong place. Please can someone advise? (I am using Oracle SQL Developer).
select
n.ordernum as "Order",
h.employee as "Name"
from ordermgmt n, orderheader h
where h.ordernum = n.ordernum
and h.employee_group IN ('ORDER.MGMT')
and h.employee is NOT NULL
and n.percentcomplete = '0'
and h.order_status !='CLOSED'
Output I am looking for would be, for example:
Name Orders Assigned
Bob 3
Peter 6
John 2
Thank you in advance
Name
Total
49
49
49
49
49
John
4
John
4
John
4
John
4
Peter
2
Peter
2
Bob
3
Bob
3
Bob
3
for example. so there are 49 blank rows summed up as 49 in the Total column. I did not add the full 49 blank columns to save space
Would be easier with sample data and expected output, but maybe you are looking for something like this
select
n.ordernum as "Order",
h.employee as "Name",
count(*) over (partition by h.employee) as OrdersAssigned
from ordermgmt n, orderheader h
where h.ordernum = n.ordernum
and h.employee_group IN ('ORDER.MGMT')
and h.employee is NOT NULL
and n.percentcomplete = '0'
and h.order_status !='CLOSED'
The use of COUNT (as other aggregate functions) is simple.
If you want to add an aggregate function, please group all scalar fields in the GROUP BY clause.
So, in the SELECT you can manage field1, field2, count(1) and so on but you must add in group by (after where conditions) field1, field2
Try this:
select
h.employee as "Name",
count(1) as "total"
from ordermgmt n, orderheader h
where h.ordernum = n.ordernum
and h.employee_group IN ('ORDER.MGMT')
and h.employee is NOT NULL
and n.percentcomplete = '0'
and h.order_status !='CLOSED'
GROUP BY h.employee

Merge the results from multiple tables side by side in PostgreSQL

I have 3 tables using with I need to make a resulting table.
Scenario:
The table 'Incoming Sentences' contains the steram of sentences
flowing in to the database.
The table 'tagged_sentences' contains
the sentences from 'incoming_sentences' which are tagged/labelled by the editor. Sometimes the admin overwrites the label if editor makes any mistake in labelling the data. Admin labelled data is final and considered to be correct.
The table 'accounts' contain the user's account level information
Below are the tables with sample information.
Incoming Sentences
id
sentence
market
model_identified_intent
tagged_at
1
abcd
en_in
alphabets
12/12/2021
2
1234
en_in
numeric
11/13/2021
3
a1b2
en_in
alphaNumeric
10/14/2021
4
efgh
en_in
alphabets
10/15/2021
5
e5f6
en_in
alphaNumeric
11/16/2021
Tagged Sentences
id
tagger_id
sentence_id
tagger_tagged_intent
1
32
1
alphabets
2
32
2
alphabets
3
32
3
Numeric
4
33
2
Numeric
5
33
3
alphaNumeric
User Account Table
id
user_role
email
name
32
editor
editor#editor.com
editor123
33
admin
admin#admin.com
admin456
Expected Output:
I want to pull the result as 'total tagged senteces per month' in one column and 'total corrections per month by the admin'. Through which the error rate can be known.
year-month
total_tagged
Total Error (Corrected by admin)
2021-10
2
1
2021-11
2
1
2021-12
1
0
Requesting your help in solving this. I tried the below code. But it isn't working as expected.
WITH cte1 AS (SELECT tggs.id id,
tggs.sentence AS sentence,
tggs.market AS market,
tggs.prod_identified_intent AS prod_identified_intent,
tggs.tagged_at AS tagged_at,
ROW_NUMBER() OVER (PARTITION BY tagged_at) AS rn
FROM tagging_sentences tggs),
cte2 AS (SELECT tgds.sentence_id_id AS sentence_id,
tgds.tagger_id_id AS tagger_id,
tgds.tagged_intent AS tagged_intent
FROM tagged_sentences tgds),
cte3 AS (SELECT acts.id AS account_id, acts.email AS email, acts.role AS role FROM accounts AS acts),
cte4 AS (SELECT tggs.tagged_at, COUNT(*) AS count, ROW_NUMBER() OVER (PARTITION BY count(*)) AS rn
FROM tagging_sentences AS tggs
JOIN tagged_sentences AS tgds ON tggs.id = tgds.sentence_id_id
JOIN accounts acts ON tgds.tagger_id_id = acts.id
WHERE tgds.tagger_id_id = 33
AND tgds.sentence_id_id IN (SELECT tagging_sentences.id
FROM tagging_sentences,
tagged_sentences
WHERE tagged_sentences.tagger_id_id = 32) GROUP BY tagged_at)
SELECT TO_CHAR(cte1.tagged_at, 'YYYY-MM'),
COUNT(cte1.sentence), cte4.count
FROM cte1
JOIN cte2 ON cte1.id = cte2.sentence_id
JOIN cte3 ON cte2.tagger_id = cte3.account_id
JOIN cte4 ON cte1.rn = cte4.rn
GROUP BY TO_CHAR(cte1.tagged_at, 'YYYY-MM'), TO_CHAR(cte4.tagged_at, 'YYYY-MM'), cte4.count;
I started trying to determine just where your initial query went awry, but there are still too many inconsistencies; columns names not defined, tables not defined, etc/ And I was not sure what all the CTEs were for. A couple seem to do nothing bu "convert" a table into a CTE (absolutely not necessary). And to attempt getting ROW_NUMBER() results to match (highly doubtful at any rate). The other issue is the magic numbers (id = 32, 33), what happens when there is another Editor and/or Admin? It just seemed overly complex.
So with that I undertook a rewrite. First I abandoned the CTE approach and used just simple Joins. An Inner Join between Incoming Sentences and Tagged Sentences and an Outer Join between Tagged Sentences and User Accounts. The twist being 2 Outer Joins, 1 getting editor role the other getting admin role. Thus removing the dependency on the magic numbers. With these in place the only thing that remained was simple counting: ( see demo )
select date_trunc( 'month', i.tagged_at) "Year Month"
, count(uae.user_role) +
count(uaa.user_role) "Total Tagged"
, count(uaa.user_role) "Total Error (Corrected by admin)"
from incoming_sentences i
join tagged_sentences t
on (t.sentence_id = i.id)
left join user_accounts uae
on ( uae.id = t.tagger_id
and uae.user_role = 'editor'
)
left join user_accounts uaa
on ( uaa.id = t.tagger_id
and uaa.user_role= 'admin'
)
group by date_trunc( 'month', i.tagged_at)
order by date_trunc( 'month', i.tagged_at);
Note: Demo includes addition of another Editor and Admin. It also shows the case where editor and admin take action in different month.
Good luck with it.

Counting the number of rows based on like values

I'm a little bit lost on this. I would like to list the number of names beginning with the same letter, and find the total amount of names containing that first same letter.
For instance:
name | total
-------|--------
A | 12
B | 10
C | 8
D | 7
E | 3
F | 2
...
Z | 1
12 names beginning with letter 'A', 10 with 'B' and so on.
This is what I have so far
SELECT
LEFT(customers.name,1) AS 'name'
FROM customers
WHERE
customers.name LIKE '[a-z]%'
GROUP BY name
However, I'm unsure how I would add up columns based on like values.
This should work for you:
SELECT
LEFT(customers.name,1) AS 'name',
COUNT(*) AS NumberOfCustomers
FROM customers
WHERE
customers.name LIKE '[a-z]%'
GROUP BY LEFT(customers.name,1)
EDIT: Forgot the explanation; as many have mentioned already, you need to group on the calculation itself and not the alias you give it, as the GROUP BY operation actually happens prior to the SELECT and therefore has no idea of the alias yet. The COUNT part you would have figured out easily. Hope that helps.
You don't want to count the names, but only the first letters. So you must not group by name, but group by the first letter
SELECT LEFT(name, 1) AS name, count(*)
FROM customers
GROUP BY LEFT(name, 1)
SQLFiddle

SQL Find consistent failures

I have a table of student ID's subjects and grades
ID SUBJECT GRADE DATE
01 math A 23/1/2013
02 eng C 22/2/2013
02 math D 24/3/2012
03 social B- 1/3/2012
03 math E 14/5/2014
......
For most subjects a fail grade is C, D or E
For math a fail grade is B-, C, D or E
I want to find students who have had a run of 5 consecutive failed grades within a cycle of 15 grades. I want to be alerted immediately after 5 happen. So for example
A A A B C C C C C A A A A B A
or
D E E E B- (maths)
After 11 passes I am not interested
D D D D A A A A A A A B B B B
I am using postgresql and am guessing that a window or aggregate function would help here?
You might like to take an approach of assigning an integer to the grades, such that 0 is a fail and 1 is a pass (depending on subject of course, and preferably looked up from a table that correlates grades and subjects to passes and fails).
The problem then reduces to, "In a series of 5 integers, is the sum equal to 0?".
Something like:
Sum(pass_fail_integer) over (partition by student
order by date
rows between 4 preceding and current row)
If a sequence of 5 fails defines the condition that you want to be warned of, I'm not clear on the significance of the cycle of 15 grades. Possibly you'd be looking for a series of 15 integers with a sum of less than 11?
Edit: if you want to confine the search to the most recent 15 grades, then a subquery that assigns a row_number to the grades per student, in date descending order, allows you to filter for the most recent 15, in which you would then apply the above logic to determine whether there are five consecutive failures.
So the general structure of the query would be:
select
distinct student
from (
select ...
sum(pass_fail_integer) over
(partition by student
order by date
rows between 4 preceding and
current row) consecutive_failures
from (
select ...
row_number() over (partition by student
order by date desc) rn
from ...)
where rn <= 15)
where consecutive_failures = 5)
You might leverage that inner query to also evaluate whether 5 failures have occurred in the 15 grade window, so you can eliminate early any students for which a check for 5 consecutive failures is not needed.