ERROR:ORA-00979: not a GROUP BY expression - sql

select frstname,addr
from medication,patient
where medication.patientnum=patient.ptnum
group by frstname,addr
having finish_date='29-01-20';
how do i solve this error?

It is very unclear what the purpose of your query is.
An immediate fix is to move the condition form the having clause to the where clause, because the column it uses is not part of the group by clause - and to use proper join syntax and date litterals:
select frstname, addr
from medication m
inner join patient p on m.patientnum = p.ptnum
where finish_date = date '2020-01-29'
group by frstname, addr
I would also warmly recommend prefixing each column with the table it belongs to, using the table aliases that I added to the query (m for medication, p for patient).
This might, or might not, do what you actually intend. If not, then you should probably ask a new question, providing sample data, expected results, and an explanation of what you are trying to accomplish.

Related

Question on getting number of day from single date column

Above is the screenshot of the tables for my practice. I want to extract the number of days between the earliest and latest sales made by staff 'Ali'. I do not have any SQL IDE to run the code and want to check any problem with my code.
SELECT DAYDIFF(day, MAX(st.Date), MIN(st.Date)) AS Duration
FROM SALES_TRANSACTION AS ST
LEFT JOIN SALES_MASTER AS sm
ON sm.Product_ID = st.Product_ID
GROUP BY sm.Staff_Name
HAVING sm.Staff_Name = 'Ali'
ORDER BY st.Date DESC
Here is the dataset
https://drive.google.com/file/d/13XCxQgbEONU22ZDYhQq-I1u-dh3A2fPc/view?usp=sharing
You want logic more like this:
SELECT DAYDIFF(day, MIN(st.Date), MAX(st.Date)) AS Duration
FROM SALES_TRANSACTION ST JOIN
STAFF_MASTER sm
ON sm.Staff_id = st.Staff_Id
WHERE sm.Staff_Name = 'Ali';
Note the changes:
The filtering is the in WHERE clause rather than the HAVING. In general, it is better to filter before aggregating if possible.
The LEFT JOIN is replaced by a JOIN. First, you need a match to get the name. Second, the foreign key reference should be valid so an outer join should not be necessary.
The correct table for the staff name is STAFF_MASTER.
If you are using SQL Server (which has the 3 argument DATEDIFF() syntax), then the smaller date is the second argument.
And finally, there are many tools on the web where you can test SQL, such as db<>fiddle, SQL Fiddle, and db-fiddle. You can also download free databases onto almost any platform.

SQL Oracle: Query of showing two columns from two tables as one and counting into numeric value

The query is:
I have a member table and a stage table, the 'band_name' is the foreign key in the members table.
I need to show the stage name (stage_name) and how many members will be performing on each stage.
I have attempted so far the following:
SELECT stage_name, member_ID,member.band_name
FROM stage, member
WHERE stage.stage_name = member.band_name
ORDER BY stage_name, member.band_name, member_ID;
This shows one stage_name and the three members but NOT as a number e.g.3 and none of the other stage_names
I think I may need to use COUNT and maybe also INNER join?
FYI - I am very new to SQL oracle
All help appreciated.
You need to learn proper, explicit, standard, readable JOIN syntax. Commas are history. JOIN is not only the future, but the present and much of the past as well.
Then, you want LEFT JOIN and GROUP BY:
SELECT stage_name, COUNT(m.member_ID)
FROM stage s LEFT JOIN
member m
ON s.stage_name = m.band_name
GROUP BY s.stage_name
ORDER BY s.stage_name;

Trying to understand how WHERE IN in a subquery works in Teradata SQL?

I'm trying to build a sub-query with a list in the where clause, I have tried several variations and I think the problem is with the way I'm structuring the WHERE IN. Help is grealy appreciated!!
SELECT a.ACCT_SK,
a.BTN,
a.PRODUCT_SET,
MAX(b.ORD_CREATD_DT)
FROM MM.MEC_ACCT_ATTR a, CDI_CRM.ORD_MSTR b
WHERE a.ACCT_SK=b.ACCT_SK AND a.BTN=b.BTN
(SELECT b.ACCT_SK, b.ORD_CREATD_DT
FROM CDI_CRM.ORD_MSTR b
WHERE b.ACCT_SK IN ('44347714',
'44023302',
'43604964'));
SELECT Failed. 3706: (-3706)Syntax error: expected something between '(' and the 'SELECT' keyword
The desired output is a table with Product set for 50 ACCT_SKs with the most recent order date matched on ACCT_SK and BTN.
Sample data and desired results would really help. Your query doesn't make much sense, but I suspect you want:
SELECT a.ACCT_SK, a.BTN, a.PRODUCT_SET,
MAX(o.ORD_CREATD_DT)
FROM MM.MEC_ACCT_ATTR a JOIN
CDI_CRM.ORD_MSTR o
ON a.ACCT_SK = o.ACCT_SK AND a.BTN = o.BTN
WHERE a.ACCT_SK IN ('44347714', '44023302', '43604964')
GROUP BY a.ACCT_SK, a.BTN, a.PRODUCT_SET;
This returns the columns you want for the three specified accounts.
Notes:
Always use proper, explicit, standard JOIN syntax. Never use commas in the FROM clause.
Your subquery simply makes no sense. It is not connected to anything else in the query.
You are using an aggregation function (MAX()) so your query is an aggregation query and needs a GROUP BY.
Use meaningful table aliases. a makes sense for an accounts table, but b does not make sense for an orders table.

Do subselects do an implicit join?

I have a sql query that seems to work but I dont really understand why. Therefore I would very much appreciate if someone could help explain whats going on:
THE QUERY RETURNS: All organisations that dont have any comments that were not created by the consultant who created the organisation record.
SELECT \"organisations\".*
FROM \"organisations\"
WHERE \"organisations\".\"id\" NOT IN
(SELECT \"comments\".\"commentable_id\"
FROM \"comments\"
WHERE \"comments\".\"commentable_type\" = 'Organisation'
AND (comments.author_id != organisations.consultant_id)
ORDER BY \"comments\".\"created_at\" ASC
)
It seems to do so correctly.
The part I dont understand is why (comments.author_id != organisations.consultant_id) is working!? I dont understand how postgres even knows what "organisations" is inside that subselect? It is not defined in here.
If this was written as a join where I had joined comments to organisations then I would totally understand how you could do something like this but in this case its a subselect. How does it know how to map the comments and organisations table and exclude the ones where (comments.author_id != organisations.consultant_id)
That subselect happens in a row so it can see all columns of that row. You will probably get better performance with this
select organisations.*
from organisations
where not exists (
select 1
from comments
where
commentable_type = 'organisation' and
author_id != organisations.consultant_id
)
Notice that it is not necessary to qualify commentable_type since the one in comments has priority over any other outside the subselect. And if comments does not have a consultant_id column then it would be possible to take its qualifier out, although not recommended for better legibility.
The order by in your query buys you nothing, just added cost.
You are running a correlated subquery. http://technet.microsoft.com/en-us/library/ms187638(v=sql.105).aspx
This is commonly used in all databases. A subquery in the WHERE clause can refer to tables used in the parent query, and they often do.
That being said, your current query could likely be written better.
Here is one way, using an outer join with comments, where no matches are found based on your criteria -
select o.*
from organizations o
left join comments c
on c.commentable_type <> 'Organisation'
and c.author_id = o.consultant_id
where c.commentable_id is null

SQL join syntax, when do you use "AS"?

I am working on an SQL statement and just wanted to clarify my understanding of join syntax in MS SQL.
Say I have the SQL...
select t.year from HOUSE AS h
LEFT OUTER JOIN SUBJECT K
ON H.Name = K.Name
INNER JOIN TESTCASE AS T
ON k.year IS NOT NULL
Sorry for the confusing example but basically - why am I able to use LEFT OUTER JOIN SUBJECT K without the keyword AS whereas with an INNER JOIN, I need to use a keyword of AS for INNER JOIN TESTCASE AS T?
'AS' is not required in either of these cases, but I prefer it personally from the point of view of readability, as it conveys exactly what you were meaning to do.
As far as I know the AS is only for easy coding. You can create a smaller or more clear name for the table. So House as H and further in the query you can use H.Name instead of typing House.Name
I believe 'AS' used to be a required keyword, but is no longer needed, only for readability. I find 'As' is often used when creating a name for a data item in the SELECT, but not when giving a name to a table in a JOIN. For example:
SELECT t.ID as TestID FROM [House] h JOIN [TestCase] t ON t.ID=h.TestID
I think this is probably because a set of data items displayed with no 'As' could become confusing as to how many items there are, and how many are just names applied to them.
interesting though where the AS keyword is useful... lets say two tables have name and you get this back from a query in code then it is cool to change the column name to something unique.