Accessing column alias in postgresql - sql

Having a little bit of trouble understanding how a query alias works in postgresql.
I have the following:
SELECT DISTINCT robber.robberid,
nickname,
Count(accomplices.robberid) AS count1
FROM robber
INNER JOIN accomplices
ON accomplices.robberid = robber.robberid
GROUP BY robber.robberid,
robber.nickname
ORDER BY Count(accomplices.robberid) DESC;
robberid | nickname | count1
----------+--------------------------------+--------
14 | Boo Boo Hoff | 7
15 | King Solomon | 7
16 | Bugsy Siegel | 7
23 | Sonny Genovese | 6
1 | Al Capone | 5
...
I can rename the "count1" column using the as command but I can't seem to be able to refer to this again in the query? I am trying to include a HAVING command at the end of this query to query only objects who have a count less than half of the max.
This is homework but I am not asking for the answer only a pointer to how I can include the count1 column in another clause.
Can anyone help?

In general, you can't refer to an aggregate column's alias later in the query, and you have to repeat the aggregate
If you really want to use its name, you could wrap your query as a subquery
SELECT *
FROM
(
SELECT DISTINCT robber.robberid, nickname, count(accomplices.robberid)
AS count1 FROM robber
INNER JOIN accomplices
ON accomplices.robberid = robber.robberid
GROUP BY robber.robberid, robber.nickname
) v
ORDER BY count1 desc

Related

Oracle issue in group by

I know this question is asked by many people. But I still couldn't figure out why this is happening. Couldn't understand this logic.
I have a table mytesttable with columns id, company_name and employee_name.
I am trying to get the employee details grouping them with respect to company name. So I used the below query:
select *
from mytesttable
group by company_name;
But I get the below issue:
ORA-00979: not a GROUP BY expression
00979. 00000 - "not a GROUP BY expression"
*Cause:
*Action:
Error at Line: 28 Column: 2
Now I have tried putting count(1) in select along with my columns, tried grouping using 2 columns etc. Still the same issue. Can anyone explain me how to achieve this?
Because this is a simple group by. Logic seems to be right, but wondering why it's not fetching me the result.
Your query is:
select *
from mytesttable
group by company_name;
The * expands to all the columns. So this becomes:
select company_name, col1, col2, col3, . . . -- your question doesn't specify the column names
from mytesttable
group by company_name;
When you specify the group by, you are specifying that there is one row per company_name in the result set. The other columns are normally filled with aggregation functions, such as MIN(), SUM(), or LISTAGG().
What value should be chosen for col1? In general, SQL does not attempt to answer this question. Instead, it returns a syntax error. This is not Oracle-specific. This is the definition of the language.
What you probably want is:
select company_name, count(*) as num_employees
from mytesttable
group by company_name;
In group by clause you have to put all selected columns. As you select all but given only one column in group by as a result it thrown error, but if you simply try like this way it will work. Actually group by used for aggregated function
select company_name, count(*) from mytesttable group by company_name;
I think you mis-understand what GROUP BY does?
It doesn't put all similar records next to each other, that's ORDER BY. What GROUP BY does is to collapse all similar records in to the same row, to allow aggregate calculations like SUM() and MIN() and COUNT(), etc.
So, two examples using the same input...
id | company_name | employee_name
----+--------------+---------------
1 | zzz | aaa
2 | xxx | bbb
3 | yyy | ccc
4 | zzz | ddd
5 | xxx | eee
Using ORDER BY...
SELECT * FROM mytesttable ORDER BY company_name, employee_name
id | company_name | employee_name
----+--------------+---------------
2 | xxx | bbb
5 | xxx | eee
3 | yyy | ccc
1 | zzz | aaa
4 | zzz | ddd
Using GROUP BY...
SELECT
company_name,
COUNT(*) number_of_employees,
MAX(id) highest_id_in_company
FROM
mytesttable
GROUP BY
company_name
ORDER BY
company_name
company_name | number_of_employees | highest_id_in_company
--------------+---------------------+-----------------------
xxx | 2 | 5
yyy | 1 | 3
zzz | 2 | 4
If you use group-by expression,you have to use aggregate functions such as max,min,average,count in select statements.
For example;
select count(*),company_name,employee_name
from mytesttable
group by company_name,employee_name
order by company_name;

Return only first row with particular value in a column

I realize that this has probably been asked a billion times, and I could swear I've done this in the past, but tonight I've got brain block or something and can't figure it out...
I have a database table ("t1") where I need to be able to retrieve only the first row where a particular value appears in a particular column.
Here's a sample of the data:
id | qID | Name
---------------------
1 | 1 | Bob
2 | 3 | Fred
3 | 1 | George
4 | 1 | Jack
What I want as a result is:
id | qID | Name
---------------------
1 | 1 | Bob
2 | 3 | Fred
The only column I actually need to get out of the query is the first one, but that's not where the duplicates need to be eliminated, and I thought it might be confusing not to show the entire row.
I've tried using this:
select id, qID, ROW_NUMBER() over(partition by qID order by qID) as zxy
from t1 where zxy = 1
But it gives me this error:
Msg 207, Level 16, State 1, Line 14
Invalid column name 'zxy'.
If I remove the where part of the query, the rest of it works fine. I've tried different variable names, using single or double quotes around 'zxy' but it seems to make no difference. And try as I might, I can't find the part of the SQL Server documentation where it discusses assigning a variable name to an expression, as in the "as zxy" part of the above query... if anybody has a link for that, that's quite useful.
Needless to say, I've tried other variable names besides "zxy" but that makes no difference.
Help!
WHERE clause is applied earlier in the process than SELECT. Therefore the calculated column zxy is not available in WHERE. In order to achieve your goal you need to put your original query in a subquery or CTE.
select id, qid
from
(
select id, qID, ROW_NUMBER() over(partition by qID order by qID) as zxy
from t1
) q
where zxy = 1
Output:
| id | qid |
|----|-----|
| 1 | 1 |
| 2 | 3 |
Here is SQLFiddle demo
Logical Processing Order of the SELECT statement
1 FROM
2 ON
3 JOIN
4 WHERE
5 GROUP BY
6 WITH CUBE or WITH ROLLUP
7 HAVING
8 SELECT
9 DISTINCT
10 ORDER BY
11 TOP
Where Clause Execute Before Select Clause so You can not find ZXY in Where cluase
with cte as
(
select id, qID, ROW_NUMBER() over(partition by qID order by qID) as zxy
from t1
)
select * from cte where zxy = 1
Here is my blog it might help you http://sqlearth.blogspot.in/2015/05/how-sql-select-statement-logically-works.html

Rewriting the HAVING clause and COUNT function

I'm trying to conceptually understand how to rewrite the HAVING clause and COUNT function.
I was asked "Find the names of all reviewers who have contributed three or more ratings. (As an extra challenge, try writing the query without HAVING or without COUNT.)" in relation this this simple database: http://sqlfiddle.com/#!5/35779/2/0
The query with HAVING and COUNT is easy. Without, I'm having difficulty.
Help would be very much appreciated. Thank you.
One option would be to use SUM(1) in place of COUNT in a subquery, and using WHERE instead of HAVING:
SELECT b.name
FROM (SELECT rID,SUM(1) Sum1
FROM rating
GROUP BY rID
)a
JOIN reviewer b
ON a.rID = b.rID
WHERE Sum1 >= 3
Demo: SQL Fiddle
Update: Some explanation of SUM(1):
Adding a constant to a SELECT statement will result in that value being repeated for every row returned, for example:
SELECT rID
,1 as Col1
FROM rating
Returns:
| rID | Col1 |
|-----|------|
| 201 | 1 |
| 201 | 1 |
| 202 | 1 |
| 203 | 1 |
| 203 | 1 |
......
SUM(1) is applying a constant 1 to every row and aggregating it.

Access query to grab +5 or more duplicates

i have a little problem with an Access query ( dont ask me why but i cannot use a true SGBD but Access )
i have a huge table with like 920k records
i have to loop through all those data and grab the ref that occur more than 5 time on the same date
table = myTable
--------------------------------------------------------------
| id | ref | date | C_ERR_ANO |
--------------------------------------------|-----------------
| 1 | A12345678 | 2012/02/24 | A 4565 |
| 2 | D52245708 | 2011/05/02 | E 5246 |
| ... | ......... | ..../../.. | . .... |
--------------------------------------------------------------
so to resume it a bit, i have like 900000+ records
there is duplicates on the SAME DATE ( oh by the way there is another collumn i forgot to add that have C_ERR_ANO as name)
so i have to loop through all those row, grab each ref based on date AND errorNumber
and if there is MORE than 5 time with the same errorNumber i have to grab them and display it in the result
i ended up using this query:
SELECT DISTINCT Centre.REFERENCE, Centre.DATESE, Centre.C_ERR_ANO
FROM Centre INNER JOIN (SELECT
Centre.[REFERENCE],
COUNT(*) AS `toto`,
Centre.DATESE
FROM Centre
GROUP BY REFERENCE
HAVING COUNT(*) > 5) AS Centre_1
ON Centre.REFERENCE = Centre_1.REFERENCE
AND Centre.DATESE <> Centre_1.DATESE;
but this query isent good
i tried then
SELECT DATESE, REFERENCE, C_ERR_ANO, COUNT(REFERENCE) AS TOTAL
FROM (
SELECT *
FROM Centre
WHERE (((Centre.[REFERENCE]) NOT IN (SELECT [REFERENCE]
FROM [Centre] AS Tmp
GROUP BY [REFERENCE],[DATESE],[C_ERR_ANO]
HAVING Count(*)>1 AND [DATESE] = [Centre].[DATESE]
AND [C_ERR_ANO] = [Centre].[C_ERR_ANO]
AND [LIBELLE] = [Centre].[LIBELLE])))
ORDER BY Centre.[REFERENCE], Centre.[DATESE], Centre.[C_ERR_ANO])
GROUP BY REFERENCE, DATESE, C_ERR_ANO
still , not working
i'm struggeling
Your group by clause needs to include all of the items in your select. Why not use:
select Centre.DATESE, Centre.C_ERR_ANO, Count (*)
Group by Centre.DATESE, Centre.C_ERR_ANO
HAVING COUNT (*) > 5
If you need other fields then you can add them, as long as you ensure the same fields appear in the select as the group by.
No idea what is going on with the formatting here!

SQL Select Statement: How to get all values from Table 'M' and any correlating values from Table 'T' or 0 if nothing

I am trying to create a query within a commercial ERP system that uses Access as its database, E2 Shop System. So it just runs the query through Access.
I want the query to tell me "how much time was logged on every machine on a prompted date, even if it is 0". I have figured out how to get it to output how much time is on a machine, but only for a machine that has time on it.
Here is the simplified example:
Table: M(machine)
Name | ID
------------
Saw | 1
Drill | 2
Weld | 3
Lathe | 4
Paint | 5
Table: T(time)
Hours | Date | Name
-------------------------
8 | 10-25 | Weld
6 | 10-25 | Saw
10 | 10-25 | Lathe
2 | 10-01 | Drill
The output I want from the query when prompted for Date 10-25 is to get:
Saw | 6
Drill | 0
Weld | 8
Lathe | 10
Paint | 0
All I can figure out is this, and it limits the output to only machines that have time against them
SELECT M.name, T.time
FROM M, T
WHERE T.Date = [ENTER DATE POSTED (MM/DD/YY):]))
ORDER BY M.ID ;
I'am thinking that CASE could help, but I can't get it to work.
The WHERE statement excludes records where the date is null, which is the case for the time table, so you need to add Or Is Null. This can get more complicated, depending on the records you want returned, you may need a sub-query.
SELECT M.Name, Nz([Hours],0) AS Hrs
FROM Machine AS M
LEFT JOIN [Time] AS T
ON M.Name = T.Name
WHERE T.Date=#10/25/2010# Or T.Date Is Null
ORDER BY M.ID;
I hope you do not really have fields called name and tables called time, because these are reserved words.
EDIT re comment
SELECT m.Name, IIf(IsNull(ts.Hours),0,ts.Hours) AS Hrs
FROM Machine AS m
LEFT JOIN (
SELECT t.Name,t.Date,t.Hours
FROM [Time] AS T
WHERE T.Date=#10/25/2010#) AS ts
ON m.Name = ts.Name;
Use a left join:
SELECT M.Name, COALESCE(T.time, 0)
FROM M
LEFT JOIN T
ON M.Name = T.Name AND T.Date = ...
ORDER BY M.Id
I don't think Access has the COALESCE though... you may be able to use Nz instead.
Related:
coalesce alternative in Access SQL