SQL: How to add a column in the SELECT query result? - sql

Usually we will select the field(s) in the SQL query. e.g.
SELECT A.id FROM Member A
But what if I want to align a column which elements correspond to the other selected field?
For example I want to select the member ID from a member table, and the COUNT that count how many times the member appear in the tuple of other table
So how do I make the COUNT column that align together with the select result?

If I understood you correctly, this is what you want:
SELECT A.id, count(B.MemberID)
FROM Member A
LEFT JOIN TableB B on A.id = B.MemberID
group by A.id
The LEFT JOIN will include records in A that do not have any corresponding records in B. Also, COUNT only counts non-null values, so you need to use it with B.MemberID. This way the count for records in A that do not have any corresponding records in B will be 0, since B.MemberID will be NULL.

I agree with #Adrian's solution, but if there were many columns in the original SELECT list, they all would have to be listed in GROUP BY. I mean something like this:
SELECT
A.id,
A.name,
A.whatever,
...
COUNT(B.member_id)
FROM Member A
LEFT JOIN Member_Something B ON A.id = B.member_id
GROUP BY
A.id,
A.name,
A.whatever,
...
It is not always convenient, especially when the columns are actually expressions. You could take another approach instead:
SELECT
A.id,
A.name,
A.whatever,
...
COALESCE(B.member_count, 0)
FROM Member A
LEFT JOIN (
SELECT member_id, COUNT(*) AS member_count
FROM Member_Something
GROUP BY member_id
) B ON A.id = B.member_id

select member_id, count(*)
from table
group by member_id;

Related

SQL - select * given count from another table

I'm trying to select * from two tables (a and b) using a join (column a.id and b.id), given that the count of a column (b.owner) in b is lower than 3, i.e. the occurence of a person's name can be max 2.
I've tried:
SELECT a.*, COUNT(b.owner) AS b_count
FROM a LEFT JOIN b on a.id = b.id
GROUP BY b.owner HAVING COUNT(b_count) <3
As im pretty new to SQL, im pretty stuck here. How can i resolve this issue? The result should be all columns for owners who do not appear more than twice in the data.
The query you are trying to run is not working due to the columns missing in the GROUP BY clause.
As you are outputting all columns from table a (with SELECT a.*), you need to include all those columns in the GROUP BY statement, so that the database understand the group of fields to group by and perform the aggregation required (in your case COUNT(b.owner)).
Example
Considering that your table a has 3 columns below:
CREATE TABLE persons (
id INTEGER,
name VARCHAR(50),
birthday DATE,
PRIMARY KEY (id)
);
.. and your table b the following and referencing the first table as below:
CREATE TABLE sales (
id INTEGER,
person_id INTEGER,
sale_value DECIMAL,
PRIMARY KEY (id),
FOREIGN KEY (person_id) REFERENCES persons(id)
);
.. you should query it aggregating the COUNT() by those 3 columns:
SELECT a.id, a.name, a.birthday, COUNT(b.person_id) AS b_count
FROM persons a
LEFT JOIN sales b ON a.id = b.person_id
GROUP BY a.id, a.name, a.birthday
HAVING COUNT(b.person_id) < 3
Alternative
In case the total of records on the 2nd table is not important to you, you could use a different "strategy" here to avoid performing the JOIN between the tables (useful when joining two huge tables) and rewriting all the columns from a on the SELECT+GROUP BY.
By identifying the records that has less than the 3 occurrences firstly:
SELECT b.person_id
FROM sales b
GROUP BY b.person_id
HAVING COUNT(b.id) < 3;
.. and using it in the WHERE clause to retrieve all the columns from the 1st table only for the ids that resulted from the previous query:
SELECT a.*
FROM persons a
WHERE a.id IN (....other query here....);
.. the execution happens in a more chronological and, perhaps, easier way to visualize while getting more familiar with SQL:
SELECT a.*
FROM persons a
WHERE a.id IN (SELECT b.person_id
FROM sales b
GROUP BY b.person_id
HAVING COUNT(b.id) < 3);
DB Fiddle here
In Standard SQL, you can use:
SELECT a.*, COUNT(b.owner) AS b_count
FROM a LEFT JOIN
b
ON a.id = b.id
GROUP BY a.id
HAVING COUNT(b.owner) < 3;
This may not work in all databases (and it assumes that a.id is unique/primary key). An alternative would be to use a correlated subquery:
SELECT a.*
FROM (SELECT a.*,
(SELECT COUNT(*)
FROM b
WHERE a.id = b.id
) as b_count
FROM a
) a
WHERE b_count < 3;

Distinct IDs from one table for inner join SQL

I'm trying to take the distinct IDs that appear in table a, filter table b for only these distinct IDs from table a, and present the remaining columns from b. I've tried:
SELECT * FROM
(
SELECT DISTINCT
a.ID,
a.test_group,
b.ch_name,
b.donation_amt
FROM table_a a
INNER JOIN table_b b
ON a.ID=b.ID
ORDER by a.ID;
) t
This doesn't seem to work. This query worked:
SELECT DISTINCT a.ID, a.test_group, b.ch_name, b.donation_amt
FROM table_a a
inner join table_b b
on a.ID = b.ID
order by a.ID
But I'm not entirely sure this is the correct way to go about it. Is this second query only going to take unique combinations of a.ID and a.test_group or does it know to only take distinct values of a.ID which is what I want.
Your first and second query are similar.(just that you can not use ; inside your query) Both will produce the same result.
Even your second query which you think is giving you desired output, can not produce the output what you actually want.
Distinct works on the entire column list of the select clause.
In your case, if for the same a.id there is different a.test_group available then it will have multiple records with same a.id and different a.test_group.

display Count of one column from another table even when the count is zero

I have two tables A and B. In Table A (Oracle sql), an unique column(not primary key) code may have some records in table B.
Example:
Code "A" has 3 entries, Code "B" has 2 entries and code "C" has 0 entries in table B. I want the query to display the code and its count of records in Table B.
A 3
B 2
C 0,
But i am not getting the code with zero records in table B, i.e C 0.
Please anyone can help me with the query.
GROUP BY with LEFT JOIN solution:
select a.code,
a.name,
count(b.code)
from A a
LEFT JOIN B b ON a.code = b.code
group by a.code, a.name
Correlated sub-query solution:
select a.code,
a.name,
(select count(*) from B b where a.code = b.code)
from A a
Perhaps you need to do SELECT DISTINCT here.
You are doing something incorrectly. This works for me:
select A.code, Count(B.code) from A
left join B on A.code = b.code
group by A.code
Fiddle: http://sqlfiddle.com/#!4/f13e1/2
It is quite easy, you just need to Take column base on you want count as I did "A.code" and don't forget to Group by that column, and use COUNT().
Check the below solution
select A.code, Count(B.code) AS Count
from A
left join B on A.code = b.code
group by A.code

Sql - Simple query with count

I have a simple question on how to read the number of occurences of some values in a table B that references to a value in a table A. It's all explained better in the following example:
Let's say I have two simple tables, A with an attribute ID and B with an attribute ID that references A.ID; I use this code to find the number of occurences of a A.ID value into B:
SELECT A.ID, COUNT(*)
FROM A JOIN B ON A.ID = B.ID
GROUP BY A.ID
Is it possible to achieve the same result using something like the following code...
SELECT ID, -- SOMETHING --
FROM A
....
... using this subquery?
SELECT COUNT(*)
FROM B WHERE B.ID = A.ID
Thank you very much
I think you might be referring to a correlated subquery:
select a.id, (select count(1) from b where id=a.id) cnt from a;
The a.id term in the subquery binds with table a in the outer query.

multi-table query when there is no record in one table

What should I do if I want to:
For now, there are table A and table B,
A:
id, name, address //the id is unique
B
id, contact, email
Since one person may have more than one contact and email, or have no contact and email(which means no record in table B)
Now I want to count how many records for each id, even 0:
And the result will look like:
id, name, contact_email_total_count
How can I do that(for now the only place I can not figure out is how to count 0 record since there is no record in table B)?
For that case you will want to use a LEFT JOIN, then add an aggregate and a GROUP BY:
select a.id,
a.name,
count(b.id) as contact_email_total_count
from tablea a
left join tableb b
on a.id = b.id
group by a.id, a.name
See SQL Fiddle with Demo
If you need help learning join syntax here is a great visual explanation of joins.
Based on your comment the typical order of execution is as follows:
FROM
ON
JOIN
WHERE
GROUP BY
HAVING
SELECT
ORDER BY
Need to do a left join to maintain the records in table A regardless of B:
PostgreSQL: left outer join syntax
Need to aggregate the count of records in B:
PostgreSQL GROUP BY different from MySQL?