SQL: group function is not allowed here - sql

I have this query
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID AND COUNT(B.*) < 4
WHERE A.STATUS = 0
In tablea, ID will have 2 row of data(2 entries), but in tableb the same ID will have upto 4 rows of data. I am trying to get the ID that has less than 4 rows of data in tableb and display that result.
so if ID 12345 is having only 2 rows of data in tableb, display that result. IF ID 98765 has 4 rows of data in tableb, ignore this entry.
But when i try the above query it says "group function is not allowed here". Please can someone help.

You can not use count() without goup by or having clause. In your case you need having
SELECT * FROM TABLEA A
INNER JOIN TABLEB B ON A.ID = B.ID
WHERE A.STATUS = 0
having COUNT(B.*) < 4
see the sqlfiddle

write it the way you would say it...
"I am trying to get the ID that has less than 4 rows of data in tableb and display that result"
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
it's not clear, but if you also only want Ids which have 2 or more rows in TableA:
SELECT * FROM TABLEA a
JOIN TABLEB b ON b.ID = a.ID
WHERE A.STATUS = 0
and (Select count(*) from TABLEB
where id = a.Id) < 4
and (Select count(*) from TABLEA
where id = a.Id) > 1

Related

I want to return status unable to do so when using groupBy

select a.NAME
from tableA a
left outer join tableB b on a.id = b.xxx_id
where a.is_deleted = false
group by a.Name having count(b.id) = 0;
Using the above code, returns the list of names.
Results:
Row NAME
1 Name1
2. Name2
3. Name3
I am using the below code to return name status.
select a.NAME, a.name_status
from tableA a
left outer join tableB b on a.id = b.xxx_id
where a.is_deleted = false
group by a.Name having count(b.id) = 0;
However, when I add a.name_status it is giving me an error saying'a.name_status in select clause is neither an aggregate nor in the group by clause.
Desired output:
Row NAME. Name_status
1 Name1 Pending
2. Name2 Expired
3. Name3. Active
Given your current query I will guess that would you want could be done using not exists, although to be sure actual sample data would help clarify.
select a.NAME, a.name_status
from tableA a
where a.is_deleted = false
and not exists (
select * from tableB b
where b.xxx_id = a.id
);

Return 1 result with left join from table B

Table A Table B Table B Table B
Itemnr Itemnr Item Status Remark
100000 100000 1 Approved
200000 100000 2 Use up
100000 3 Obsolete
200000 1 Approved
200000 2 Use up
200000 3 Obsolete
I would like to see only one result per line in table A item with as result the Remark based on Item status 1. I tried a lot with the option of a left join but without the good result.
Is this what you want?
select a.itemnr, b.remark
from tablea a
inner join tableb b on b.itemnr = a.itemnr and b.item_status = 1
If some records in tablea might not have a corresponding row in tableb with item_status = 1 and you want to keep these in the resultset, then you can use left join instead of inner join.
For the data example you have provided, you don't need tablea:
select b.itemnr, b.remark
from tableb b
where b.item_status = 1;
You specify that you want a left join, which implies rows in tablea that are not in tableb, although you have no such examples in the question. In that case:
select a.itemnr, b.remark
from tablea a left join
tableb b
on b.itemnr = a.itemnr and b.item_status = 1;
You can use row_number()
select t.*
from (select a.*, b.*, row_number() over (partition by a.itemr order by b.status) as seq
from a inner join
b
on a.itemr = b.itemr
) t
where seq = 1;
This will return rows total itemrs along with first status. Also this assumes Itemnr, Item Status, Remark are the columns name.
EDIT : If you want to check, first status 1 is available or not then you can do :
SELECT a.itemr, b.remark
FROM a LEFT JOIN
b
ON b.itemr = a.itemr AND b.status = 1;

Query two tables - return Items that are not in both

I have two tables like this :
TableA
Id | ProjectId | JobId
TableB
Id | Title
I want to write a query returning TableB Ids that are not in TableA with ProjectId = 2.
I've written a query like
Select B.Id
From TableB B
Right Join TableA A On B.Id = A.JobId
Where B.JobId Is Null And A.ProjectId = 2
But it returns zero output.
Thanks
I would use EXISTS here:
SELECT b.Id
FROM TableB b
WHERE NOT EXISTS (SELECT 1 FROM TableA a WHERE a.JobId = b.Id AND a.ProjectId = 2);
Reading in English terms, the above says to select every Id in TableB such that we cannot find an equal Id in TableA whose ProjectId is also 2.
Query edited

SQL Server: how can I count values in one field different from another, with multiple values for same identifier?

I have two tables with one common column, and an identifying value that can be duplicate (several observations of same document).
An example:
TableA:
A_identifier | Value
-------------+-------
1 | A
1 | B
TableB:
B_identifier | A_identifier | Value
-------------+--------------+-------
1 | 1 | A
2 | 1 | B
3 | 1 | B
4 | 1 | C
The above example illustrates the type of situation I am looking for in my data - we have a case in TableA with multiple values, of which some are the same in TableB and some are not. So TableA.Value and TableB.Value represent the same concept.
I want to know for each TableA.A_identifier, how many rows of TableB have different values than TableA.Value. If there was only one observation per A_identifier, this could be solved with a not, but the multiple possible values prevent this.
What I have thought about doing is something like this (which does not work):
select distinct
b.B_identifier, a.A_identifier
from
TableB b
join
TableA a in b.A_identifer = a.A_identifier and b.Value != a.Value
While the query technically works, it returns the wrong result - it counts all the cases where the values in TableA and TableB are different in a given row. However, I want it to only count the values in TableB which are not present at all in TableA for each A_identifier.
I tried replacing the != with not in which is what I would do for a static parameter. This syntax is not supported.
I hope my question makes sense, and that somebody can help. Thank you in advance.
Try this query if it works for you,
SELECT COUNT(b.A_identifier)
FROM TableB b
LEFT JOIN TableA a
ON b.A_identifier = a.A_identifier
AND b.Value = a.Value
WHERE a.A_identifier IS NULL -- filters out inexisting value
AND EXISTS (SELECT 1
FROM TableA c
WHERE b.A_identifier = c.A_identifier) -- shows only A_identifier
-- that is present in TableA
However, if you want to get the count for each Value
SELECT b.A_identifier, b.Value, TOTAL_COUNT = COUNT(b.A_identifier)
FROM TableB b
LEFT JOIN TableA a
ON b.A_identifier = a.A_identifier
AND b.Value = a.Value
WHERE a.A_identifier IS NULL
AND EXISTS (SELECT 1
FROM TableA c
WHERE b.A_identifier = c.A_identifier)
GROUP BY b.A_identifier, b.Value
Use NOT EXISTS
select t1.A_identifier, count(t2.value)
from TableA t1
left join TableB t2 on t1.A_identifier = t2.A_identifier and
NOT EXISTS (
select 1
from TableA t3
where t3.A_identifier = t2.A_identifier and
t3.Value = t2.Value
)
group by t1.A_identifier
How about the following SQL?
select distinct TableA.A_identifier,
(select count(*) from TableB
where TableB.A_identifier = TableA.A_identifier
and not exists(
select * from TableA where A_identifier = TableB.A_identifier
and Value = TableB.Value)
)
as TableB_Rows
from TableA

Select all from one table and count from another and include nulls

I'm trying to get all ids from one table and a count of transactions from another table. The trick is that an id may not be listed in the transaction table. In that case, I want the query to return 0 for that id. (I apologize for the bad formatting)
ID Table
ID
1
2
3
Trans Table
ID Trans
1 123
1 234
3 345
3 456
3 567
Query results
ID - Trans Count
1 2
2 0
3 3
I have this code, but it just isn't working for me and I can't figure out why.
SELECT A.ID, COUNT (B.TRANS) AS CNT
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND
A.CURRENT_FLAG = 1
GROUP BY A.ID
When using left join, conditions on the first table go in the where clause. Conditions on the second table go in the on clause:
SELECT A.ID, COUNT (B.TRANS) AS CNT
FROM A LEFT JOIN
B
ON A.ID = B.ID AND
B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND
WHERE A.CURRENT_FLAG = 1
GROUP BY A.ID;
I would check if the value is null if then just replace it with a 0
The NVL Function will work perfect for this scenario.
SELECT A.ID, COUNT (NVL(B.TRANS,0)) AS CNT
FROM A
LEFT JOIN B
ON A.ID = B.ID
WHERE B.DTE BETWEEN '01-Mar-2017' AND '31-Mar-2017' AND A.CURRENT_FLAG = 1
GROUP BY A.ID