I have following tables:
table1 id, plan_name
table2 id, service_class_name,
table3 id, plan_has_service_id
table4 id, service_course_name
table5 id, service_type_name
table6 id, service_type_has_service_name
I want to create query which will return rows of data: plan_name,service_name,service_course_name,which course and class under its plan and their types like is it class or course
i have tried following query:
SELECT
phs.id id,
phs.plan_id AS Plan_Has_Service_plan_id,
phs.service_class_id AS Plan_Has_Service_service_id,
phs.service_course_id AS Plan_Has_Service_service_course_id,
plan.plan_name AS plan_name,
services_x.service_class_name AS service_name,
services_x.service_class_description AS service_description,
services_x.service_class_price AS service_price,
services_x.is_service_class_active AS is_service_active,
services_x.service_class_image_url AS service_image_url,
sths_x.service_type_id AS service_type_has_service_service_type_class_id,
service_type_x.typeofservice service_type_name_class
FROM ((((public."tbl_stu_adm-pricing_plan-plan_has_service_class_course" phs
JOIN public."tbl_stu_adm-pricing_plan-plan"
plan ON phs.plan_id=plan.id)
JOIN public."tbl_stu_adm-pricing_plan-service_class" services_x
ON phs.service_class_id=services_x.id)
JOIN public."tbl_stu_adm-pricing_plan-service_type_has_service"
sths_x ON phs.service_class_id=sths_x.service_id)
JOIN public."tbl_stu_adm-pricing_plan-service_type" service_type_x
ON sths_x.service_type_id=service_type_x.id)
UNION
SELECT
phs.id id,
phs.plan_id AS Plan_Has_Service_plan_id,
phs.service_class_id AS Plan_Has_Service_service_id,
phs.service_course_id AS Plan_Has_Service_service_course_id,
plan.plan_name AS plan_name,
services_y.service_course_name AS service_name,
services_y.service_course_description AS service_description,
services_y.service_course_price AS service_price,
services_y.is_service_course_active AS is_service_active,
services_y.service_course_image_url AS service_image_url,
sths_x.service_type_id AS service_type_has_service_service_type_class_id,
service_type_x.typeofservice service_type_name_class
FROM ((((public."tbl_stu_adm-pricing_plan-plan_has_service_class_course" phs
JOIN public."tbl_stu_adm-pricing_plan-plan"
plan ON phs.plan_id=plan.id)
JOIN public."tbl_stu_adm-pricing_plan-service_course" services_y
ON phs.service_course_id =services_y.id)
JOIN public."tbl_stu_adm-pricing_plan-service_type_has_service"
sths_x ON phs.service_course_id=sths_x.service_id)
JOIN public."tbl_stu_adm-pricing_plan-service_type" service_type_x
ON sths_x.service_type_id=service_type_x.id)
Here is sample from that query:
id plan_name service type
1, free Class 11 Class
1, free course Class
2, free Class 11 Class
I want result like that:
id plan_name service type
1, free Class 11 Class
1, free course Course
2, free CourseTwo Course
But Class 11 is showing two times and Course type showing Class
Related
how to find number of records in both table using join.
i have two tables table1 and table2 with same structure.
table1
id
item
1
A
1
B
1
C
2
A
2
B
table2
id
item
1
A
1
B
2
A
2
B
2
C
2
D
Output should be like this.
id
table1.itemcount
table2.itemcount
1
3
2
2
2
4
SELECT DISTINCT id, (
SELECT COUNT(*) FROM table1 AS table1_2 WHERE table1_2.id=table1.id
) AS "table1.itemcount", (
SELECT COUNT(*) FROM table2 AS table2_2 WHERE table2_2.id=table1.id
) AS "table2.itemcount"
FROM table1;
Assuming that each id is guaranteed to exist in both tables, the following would work
select
t1.id,
count(distinct t1.item) t1count,
count(distinct t2.item) t2count
from t1
join t2 on t1.id = t2.id
group by 1;
But if that is not guaranteed then we'll have to use full outer join to get unique ids from both tables
select
coalesce(t1.id, t2.id) id,
count(distinct t1.item) t1count,
count(distinct t2.item) t2count
from t1
full outer join t2 on t1.id = t2.id
group by 1;
We're using coalesce here as well for id because if it only exists in t2, t1.id would result in null.
#DeeStark's answer also works if ids are guaranteed to be in both tables but it's quite inefficient because count is essentially run twice for every distinct id in the table. Here's the fiddle where you can test out different approaches. I've prefixed each query with explain which shows the cost
Hope this helps
I have a scenario to extract information from three(Table1, Table2, Table4) tables based on the common id of Table1
For extracting information from Table 4, I have to look another intermediate table(Table3) for the common Id between Table 3 and Table 4. The query result of Table 4 information would contain more than a single row as query response.
I have written the following HQL(Hibernate Query) for my requirement
select t1,t2,(select t4.column1 from Table4 t4
join Table3 t3 on t4.column0=t3.column0 and t3.column1=t1 and t3.column2='desired_value') from Table1 t1
join Table2 t2 on t2.column1=t1.column1
where t1.column0=:id and t1.column3=:value
I have entity classes for all the four tables.
How can I select the multiple rows from the subquery
What is the euiquvalent of POSTGRESQL array_agg() / string_agg() method in Spring Data JPA?
Without the subquery, I am able to fetch Object[] response with my Entity class objects.
How can I add my subquery in order to retrieve all my desired data in a Single transaction without creating a separate query method in my Repository class?
What I tried so far:
select t1,t2,(select new List(t4.column1) from Table4 t4
join Table3 t3 on t4.column0=t3.column0 and t3.column1=t1 and t3.column2='desired_value') from Table1 t1
join Table2 t2 on t2.column1=t1.column1
where t1.column0=:id and t1.column3=:value
Below is the output object that I am trying to achieve:
List<Object[]> as my query response
where each Object[] will be of size 3 with following
Object[0] -> Table1_Entity object
Object[1] -> Table2_Entity object
Object[2] -> will be a String[] containing a specific column values from Table4 Entity class
i.e response = [[obj1, obj2, ["value1, value2","value3"]], [obj3, obj4, ["value1, value2","value3"]], ......]
Try this:
select t1,t2, (select cast(function('string_agg', t4.column1, ', ') as string) from Table4 t4
join Table3 t3 on t4.column0=t3.column0 and t3.column1=t1 and t3.column2='desired_value') from Table1 t1
join Table2 t2 on t2.column1=t1.column1
where t1.column0=:id and t1.column3=:value
If I am in the situation where I have a n+1 problem I normally use the JPA "join fetch" keyword if it is only one indirection (i. e. select p from Person p join fetch p.address) or if it is more than one indirection I use a JPA provider-proprietary query hint, which is in my case eclipselink (i. e. select p from person with the query hint eclipselink.join-fetch=p.address.city). Thats well explained in the article Java Persistence Performance.
Anyway, lately I stumbled over a datamodel where two entities where subclassed by another one.
I have an Account which owns a Contact. A Contact itself is a abstract superclass which is extended by a Person or a Company. And a Person does have a relationship to a list of Hobbyies.
#Entity
public class Account
{
#OneToOne
private Contact contact;
}
#Entity
#Inheritance(strategy = InheritanceType.JOINED)
public abstract class Contact {}
#Entity
public class Person extends Contact
{
#OneToMany
private List<Hobby> hobbies;
}
#Entity
public class Company extends Contact {}
I need to load a list of Accounts, select a from Account a. I surely ran into the n+1 problem, because of the hobbies. No problem I thought, with the two above mentioned and well probed solutions I can cope with the n+1 problem. But soon I realized that does not work.
select a from Account a join fetch a.contacts does not fetch the hobbies. Nor does select a from Account a with the query hint eclipselink.join-fetch=a.contacts. And select a from Account a with the query hint eclipselink.join-fetch=a.contacts.hobbies throws a
... navigated to a non-existent relationship-Exception.
I also tried to use the JPA treat-function i. e. select a from Account a join fetch treat(a.contact as Person) p join fetch p.hobbies, but that does not fetch the hobbies and only fetches the Persons and not the Companies along.
Does anyone have an idea how to use join fetch or eclipselink query hints to accomplish such a query optimization?
EDIT
In order to answer the comment by Chris.
The #BatchFetch annotation at the hobbies does not have any impact on the query. There is no difference to the queries without it.
Here are the sqls generated by each query with the #BatchFetch annotation
select a from Account a
1 SELECT id, contact_id FROM account
2 SELECT DISTINCT DTYPE FROM contact WHERE (ID = ?)
3 SELECT t0.ID, t0.DTYPE, t1.ID, t1.FOUNDED FROM contact t0, company t1 WHERE ((t0.ID = ?) AND ((t1.ID = t0.ID) AND t0.DTYPE = ?))
4 SELECT DISTINCT DTYPE FROM contact WHERE (ID = ?)
5 SELECT t0.ID, t0.DTYPE, t1.ID, t1.NAME FROM contact t0, person t1 WHERE ((t0.ID = ?) AND ((t1.ID = t0.ID) AND (t0.DTYPE = ?)))
6 SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
... (repetition of lines 2 to 6)
select a from Account a join fetch a.contacts
SELECT t3.ID, t3.contact_id, t0.ID, t0.DTYPE, t1.NAME, t2.ID, t2.FOUNDED FROM contacts t0 LEFT OUTER JOIN person t1 ON (t1.ID = t0.ID) LEFT OUTER JOIN company t2 ON (t2.ID = t0.ID), account t3 WHERE (t0.ID = t3.contact_id)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
SELECT ID, OUTDOOR, PERSON_ID FROM hobby WHERE (PERSON_ID = ?)
...
I have a difficulty dealing with a SQL query. I use PostgreSQL.
The query says: Show the customers that have done at least an order that contains products from 3 different categories. The result will be 2 columns, CustomerID, and the amount of orders. I have written this code but I don't think it's correct.
select SalesOrderHeader.CustomerID,
count(SalesOrderHeader.SalesOrderID) AS amount_of_orders
from SalesOrderHeader
inner join SalesOrderDetail on
(SalesOrderHeader.SalesOrderID=SalesOrderDetail.SalesOrderID)
inner join Product on
(SalesOrderDetail.ProductID=Product.ProductID)
where SalesOrderDetail.SalesOrderDetailID in
(select DISTINCT count(ProductCategoryID)
from Product
group by ProductCategoryID
having count(DISTINCT ProductCategoryID)>=3)
group by SalesOrderHeader.CustomerID;
Here are the database tables needed for the query:
where SalesOrderDetail.SalesOrderDetailID in
(select DISTINCT count(ProductCategoryID)
Is never going to give you a result as an ID (SalesOrderDetailID) will never logically match a COUNT (count(ProductCategoryID)).
This should get you the output I think you want.
SELECT soh.CustomerID, COUNT(soh.SalesOrderID) AS amount_of_orders
FROM SalesOrderHeader soh
INNER JOIN SalesOrderDetail sod ON soh.SalesOrderID = sod.SalesOrderID
INNER JOIN Product p ON sod.ProductID = p.ProductID
HAVING COUNT(DISTINCT p.ProductCategoryID) >= 3
GROUP BY soh.CustomerID
Try this :
select CustomerID,count(*) as amount_of_order from
SalesOrder join
(
select SalesOrderID,count(distinct ProductCategoryID) CategoryCount
from SalesOrderDetail JOIN Product using (ProductId)
group by 1
) CatCount using (SalesOrderId)
group by 1
having bool_or(CategoryCount>=3) -- At least on CategoryCount>=3
See query below
Select count(*) FROM
(Select distinct Student_ID, Name, Student_Age, CourseID from student) a1
JOIN
(Select distinct CourseID, CourseName, TeacherID from courses) a2
ON a1.CourseID=a2.CourseID
JOIN
(Select distinct TeacherID, TeacherName, Teacher_Age from teachers) a3
ON a2.TeacherID=a3.TeacherID
The subqueries must be used for deduping purpose.
This query run fine in PostgreSQL. However, if I add a condition between the student and teacher table, according to the execution plan, Postgres will wrongly nested loop join the student and teach tables which have no direct relationship. For example:
Select count(*) FROM
(Select distinct Student_ID, Name, Student_Age, CourseID from student) a1
JOIN
(Select distinct CourseID, CourseName, TeacherID from courses) a2
ON a1.CourseID=a2.CourseID
JOIN
(Select distinct TeacherID, TeacherName, Teacher_Age from teachers) a3 ON
a2.TeacherID=a3.TeacherID
WHERE Teacher_Age>=Student_Age
This query will take forever to run. However, if I replace the subqueries with the tables, it'll run very fast. Without using temp tables to store the deduping result, is there a way to to avoid the nested loop in this situation?
Thank you for your help.
You're making the database perform a lot of unnecessary work to accomplish your goal. Instead of doing 3 different SELECT DISTINCT sub-queries all joined together, try joining the base tables directly to each other and let it handle the DISTINCT part only once. If your tables have proper indexes on the ID fields, this should run rather quick.
SELECT COUNT(1)
FROM (
SELECT DISTINCT s.Student_ID, c.CourseID, t.TeacherID
FROM student s
JOIN courses c ON s.CourseID = c.CourseID
JOIN teachers t ON c.TeacherID = t.TeacherID
WHERE t.Teacher_Age >= s.StudentAge
) a