I want to concat group name with the number of the students of the group with another parameter to select groups from Groups table
Like this :
Group1 -- 250 std
Group2 -- 243 std
Groups and students are separated tables and foreign key in Groups table used to select target groups
I have a two tables one of them has std data with group Id as foreign key and groups table has groups data and a foreign key for subject
I need to get all the groups which coresponding with subject id I want and count the std of each group ,concat it with the group name
Read about SQL Joins here
https://www.w3schools.com/sql/sql_join.asp
A join retrieves columns from different tables by relating two rows using an ON clause
Related
The following table contains two grouping variables, id_point and sci_name and a continuous variable distance. There are multiple distance values per unique combinations of id_point and sci_name. I would like to create a table that contains each unique combination between id_point and sci_name and the minimum distance value.
This was my best attempt:
CREATE TABLE sar.test AS
SELECT DISTINCT id_point, sci_name, MIN(distance)
GROUP BY id_point, sci_name,
FROM sar.dist_mam_na;
The GROUP BY goes after the FROM, and by definition of aggregation, the groups will be unique so the DISTINCT is irrelevant:
SELECT id_point, sci_name, MIN(distance)
FROM sar.dist_mam_na
GROUP BY id_point, sci_name
I have the following 2 tables (there are more fields in the real tables):
create table publisher(id serial not null primary key,
name text not null);
create table product(id serial not null primary key,
name text not null,
publisherRef int not null references publisher(id));
Sample data:
insert into publisher (id,name) values (1,'pub1'),(2,'pub2'),(3,'pub3');
insert into product (name,publisherRef) values('p1',1),('p2',2),('p3',2),('p4',2),('p5',3),('p6',3);
And I would like the query to return:
name, numProducts
pub2, 3
pub3, 2
pub1, 1
A product is published by a publisher. Now I need a list of name, id of all publishers which have at least one product, ordered by the total number of products each publisher has.
I can get the id of the publishers ordered by number of products with:
select publisherRef AS id, count(*)
from product
order by count(*) desc;
But I also need the name of each publisher in the result. I thought I could use a subquery like:
select *
from publisher
where id in (
select publisherRef
from product
order by count(*) desc)
But the order of rows in the subquery is lost in the outer SELECT.
Is there any way to do this with a single sql query?
SELECT pub.name, pro.num_products
FROM (
SELECT publisherref AS id, count(*) AS num_products
FROM product
GROUP BY 1
) pro
JOIN publisher pub USING (id)
ORDER BY 2 DESC;
db<>fiddle here
Or (since the title mentions "all data") return all columns of the publisher with pub.*. After products have been aggregated in the subquery, you are free to list anything in the outer SELECT.
This only lists publisher which
have at least one product
And the result is ordered by
the total number of products each publisher has
It's typically faster to aggregate the "n"-table before joining to the "1"-table. Then use an [INNER] JOIN (not a LEFT JOIN) to exclude publishers without products.
Note that the order of rows in an IN expression (or items in the given list - there are two syntax variants) is insignificant.
The column alias in publisherref AS id is totally optional to use the simpler USING clause for identical column names in the following join condition.
Aside: avoid CaMeL-case names in Postgres. Use unquoted, legal, lowercase names exclusively to make your life easier.
Are PostgreSQL column names case-sensitive?
I am working with my lab database and close to complete it. But i am stuck in a query and a few similar queries which all give back the similar results.
Here is the Query in design mode
and this is what it gives out
This query is counting the number of ID values in table PatientTestIDs whereas I want to count the number of unique PatientID values grouped by each department
I have even tried Unique Values and Unique Records properties but all the times it gives the same result.
What you want requires two queries.
Query1:
SELECT DISTINCT PatientID, DepartmentID FROM PatientTestIDs;
Query2:
SELECT Count(*) AS PatientsPerDept, DepartmentID FROM Query1 GROUP BY DepartmentID;
Nested all in one:
SELECT Count(*) AS PatientsPerDept, DepartmentID FROM (SELECT DISTINCT PatientID, DepartmentID FROM PatientTestIDs) AS Query1 GROUP BY DepartmentID;
You can include the Departments table in query 2 (or the nested version) to pull in descriptive fields but will have to include those additional fields in the GROUP BY.
Problem Statement
I would like to select all of the resources that belong to a certain company, for each resource I would like to get a comma separated list of the groups that it belongs to (using string_agg).
DB Relationships
Resources
=============================
ResourceId (PK)
CompanyId (FKs to Company)
ResourceName
...
Other columns that are not important
Company
=============================
CompanyId (PK)
...
Other columns that are not important
GroupResources
=============================
GroupId (PK and FKs to Group)
ResourceId (PK and FKs to Resources)
Group
=============================
GroupId (PK)
CompanyId (FKs to Company)
GroupName
...
Other columns that are not important
What I currently have
I currently have two separate queries, Query A which retrieves all of the information I require except for the aggregate of the groups for each resource, and Query B which retrieves only the aggregate of the groups for each resource in the company.
Query A
SELECT resources.resourcename, ... other columns that I am selecting out
FROM resources
...
JOINs to tables to get date for some of the other columns
...
WHERE resources.companyid = 1234
ORDER BY resourcename ASC;
Query B
SELECT string_agg(groupname, ',') AS groups
FROM group
JOIN groupresources USING (groupid)
JOIN resources USING (resourceid)
WHERE resources.companyid = 1234
GROUP BY (resourcename)
ORDER BY groups ASC;
I know about using subqueries but in this case I'm not quite sure about how to apply that knowledge because it seems like I am trying to perform what would be a two part operation (in languages such as C#) in a single hit:
Get all of the resources for a company
Populate the groups property for each resource
Simply adding the string_agg statement to Query A will return an aggregated string for all groups in the company, NOT just the ones the resource is part of. This was an incorrect assumption that I was making, see answer for more details.
Desired Output
resource1, 'group1,group 2', ...other columns
resource2, 'group3', ...other columns
resource3, 'group1, group3', ...other columns
My assumption that adding string_agg to Query A would return a comma separated list of values for all of the groups in a company, rather than just the groups that the resource in the row belonged to was in correct.
In actual fact adding string_agg to Query A forced the use of the GROUP BY command because I had other columns that I was selecting outside of the aggregrate function (...column must appear in the GROUP BY clause or be used in an aggregate function...). Once I added the relevant columns (everything except the aggregated column) to the GROUP BY clause, my query functioned as expected.
Penultimate Query
SELECT
resources.resourcename,
... other columns that I am selecting out...
string_agg(groupname, ', ') AS Groups
FROM resources
...
JOINs to tables to get data for some of the other columns
LEFT JOIN groupresources USING (resourceid)
LEFT JOIN group USING (groupid)
LEFT JOIN resources USING (resourceid)
...
WHERE resources.companyid = 1234
GROUP BY
resourcename,
...all other columns except the one inside the string_agg function...
ORDER BY resourcename ASC;
The GROUP BY ensured that I was getting results for the groups a resource belonged to, rather than all groups within a company.
...however this was still excluding some rows as I knew the expected number of resources, and my result was less than this.
I discovered that I could achieve a similar effect using a SELECT inside a JOIN.
Final Query
SELECT
resources.resourcename,
... other columns that I am selecting out...
Groups
FROM resources
...
JOINs to tables to get data for some of the other columns
LEFT JOIN resources USING (resourceid)
LEFT JOIN
(
SELECT
resourceid,
string_agg(groupname,', ' ORDER BY groupname) AS Groups
FROM tgroupresources
JOIN tgroup USING (groupid)
GROUP BY resourceid
) AS g USING (resourceid)
...
WHERE resources.companyid = 1234
ORDER BY resourcename ASC;
Which returned the full result set.
I have two tables: Employee and Training, Employee table has two columns: ID (numeric) and Name (text).
Training table also has two columns: No (numeric) and TrainingName (text).
My boss asked me the following:
Some trainingName can be classified by “group name” (group name can dynamically be added by user input) and one traininName can be classified in one group, no group or more than one group. Each employee can be under one group or no group.(can not be under two or more groups).
I am confused in how to manage that? Do I need to create another table or modify the existing tables?
I am using PostgreSQL9.2.
You'll need to add two more tables: "groups", and "groups_trainings".
This will be your resulting Database-Layout:
employees:
id
name
group (foreign key to groups.id; can be null)
trainings:
id
trainingName
groups:
id
groupName
groups_trainings
id
trainingID (foreign key to trainings.id)
groupID (foreign key to groups.id)
You need the last table, to map n groups to n trainings.
The layout says the following:
Each empoyee belongs to one group, or no group (employees.group is null)
Each group can contain 0 or more trainings.
Each training can be part of 0 or more groups