Inserting information from an Inner Join - java

I currently have 3 tables and an inner join containing all the tables.
SELECT I.idInvoice
, C.idCustomer
, C.FirstName
, C.Surname
, P.idProduct
, P.Quantity
, I.Date
, P.PName
, P.Price
, I.QuantityOrdered
FROM Invoice I
JOIN Customer C
on I.idCustomer = C.idCustomer
JOIN PRODUCT P
on I.idProduct = P.idProduct
LIMIT 0, 1000
I'm taking values from text labels, but the only problem is, I don't how to insert all the data into their respective tables. E.g. FirstName into Customer and Quantity into Product.

Related

Postgres query to find multiple records with a particular repeat count within a table

I have 2 tables Customer and Orders.
1st question:
That is a master table for Customers that have a few columns like Customer number, customer name, Active flag, etc. Table may contain 2 or more records for the same customer number but as per the business logic only 1 records at a time should ideally be ACTIVE. I need to find customers that have only 1 record and it should be active.
query that I have written:
select customer_number, count(*)
from customers c
where active = false
group by customer_number
having count(*) = 1;
This returns me the customers that have 2 records and only 1 is NOT ACTIVE.
Question 2:
Apart from customer table we have another table that is Orders table, it contains columns like Customer number(as same in Customers table), deliver date, order number, insert time.
I need to find the customers whose ACTIVE is false, and have not given any orders since 180 days. (INSERT TIME::date - 180).
what I have tried is not giving me the desired output, as on back testing I found that the data is wrong
select om.customer_number,
c.customer_name,
om.deliverydate,
om.insert_time
from customers c, order_master om
where
om.customer_number in
(
select c2.customer_number
from customers c2
where c2.active = false
group by c2.customer_number
having count(*) =1
)
and c.customer_number = om.customer_number
group by om.customer_number, c.customer_name,
om.deliverydate, om.insert_time
having max(om.insert_time::date) < '2022-06-01' ;
The queries that I have tried, I have already mentioned them in my question. Please check that.
For the first question, find customers that have only 1 record and it should be active , you may use conditional aggregation or filtered count as the following:
select customer_number
from Customers c
group by customer_number
having count(*) = 1 and count(*) filter (where active) = 1;
For the second question, find the customers whose ACTIVE is false, and have not given any orders since 180 days, try the following:
select cu.customer_number
from order_master om join
(
select customer_number
from Customers c
group by customer_number
having count(*) filter (where active) = 0
) cu
on om.customer_number = cu.customer_number
group by cu.customer_number
having max(om.insert_time) < current_date - interval '180 day'
See a demo.
If you want to get all order details for the inactive customers, you may join the above query with the orders table as the following:
with inactive_cust as
(
select cu.customer_number, cu.customer_name
from order_master om join
(
select customer_number, customer_name
from Customers c
group by customer_number, customer_name
having count(*) filter (where active) = 0
) cu
on om.customer_number = cu.customer_number
group by cu.customer_number, cu.customer_name
having max(om.insert_time) < current_date - interval '180 day'
)
select c.customer_number, c.customer_name,
o.order_number, o.insert_time
from inactive_cust c join order_master o
on c.customer_number = o.customer_number
See a demo.
#Ahmed- Both of your queries worked fine.
However in the 2nd query I want to fetch additional data into it, so what I did was -
select om.customer_number, cu.customer_name, om.order_number ,om.insert_time
from order_master om join
(
select customer_number, customer_name
from Customers c
group by customer_number, customer_name
having count(*) filter (where active) = 0
) cu
on om.customer_number = cu.customer_number
group by om.customer_number , cu.customer_name, om.insert_time,om.order_number
having max(om.insert_time) < current_date - interval '180 day';
When I tried the query shared by you -
select om.customer_number
from order_master om join
(
select customer_number
from Customers c
group by customer_number
having count(*) filter (where active) = 0
) cu
on om.customer_number = cu.customer_number
group by om.customer_number
having max(om.insert_time) < current_date - interval '180 day';
Its giving me around 4K results, and when I am trying with my modifications, so after adding each column in the query the result count is increasing exponentially till 75K and more.
Also its showing me records for which max(om.insert_time) is much greater than 180 days

Unable to form a single query to join multiple tables

I have to write a single select query to fetch all details from seven tables. Earlier I had separate queries but now I am working on optimizing the queries.
The following is my table structure :
Main Table (SN, model , regId) -- 1 row
Table1(col1,col2....SN) - SN is forienKey -- 1 row
Table2(col1,col2,....SN) - SN is forienKey -- 1 row
Table3(col1,col2,.....regId) - regId is forienKey -- 1 row
Table4(col1,col2,.....regId) - regId is forienKey - 2 rows
Table5(col1,col2,.....regId) - regId is forienKey - 2 rows
Table6(col1,col2,.....regId) - regId is forienKey - 1 row
There is a one to many mapping between the main table and table 4 and table 5.
I have tried using inner join to fetch the rows but I am getting duplicate values. Below is the query that I have written. Is there anything I am missing?
select * from MainTable
inner join Table1 on MainTable.SN = Table1.SN
inner join Table2 on MainTable.SN = Table2.SN
inner join Table3 on MainTable.regId = TABLE3.regId
inner join TABLE4 on MainTable.regId = Table4.regId
inner join TABLE5 on MainTable.regId = Table5.regId
inner join TABLE6 on MainTable.regId = Table6.regId
try joining tables like below to join all of them together
select * from (select * from MainTable
inner join Table1 on MainTable.SN = Table1.SN
inner join Table2 on Table1.SN = Table2.SN ) tempMain
inner join Table3 on tempMain.regId = TABLE3.regId
inner join TABLE4 on TABLE3.regId = Table4.regId
inner join TABLE5 on Table4.regId = Table5.regId
inner join TABLE6 on Table5.regId = Table6.regId
though from your example i don't know if table2 & table 3 are related. anyways you can try to find similar.

Are these SQL queries equivalent? And which is better or is there a better option?

I am working on a Spring web application that utilizes hibernate to connect to a DB2 database. I am try to optimize a service method that gets called may times during a wed service call by reducing the number of DB queries.
So my question is whether or not this query
SELECT DISTINCT a.* FROM TABLE_A a
LEFT JOIN TABLE_B b ON a.ID = b.FK_ID
LEFT JOIN TABLE_C c ON a.ID = c.FK_ID
LEFT JOIN TABLE_D d ON c.DATA_RQST_ID = d.ID
WHERE (b.REQUEST_ID = 1234 AND b.TYPE = 'TYPE_A')
OR (c.REQUEST_ID = 1234 AND (c.TYPE = 'TYPE_A' OR c.TYPE = 'TYPE_B'))
is equivalent/better then this query
SELECT * FROM TABLE_A a
WHERE a.ID IN
(
SELECT b.FK_ID FROM TABLE_B b
WHERE b.REQUEST_ID = 1234 AND eb.TYPE = 'TYPE_A'
)
OR a.ID IN
(
SELECT c.FK_ID FROM TABLE_C
WHERE ( c.REQUEST_ID = 1234 AND c.TYPE = 'TYPE_A' )
OR
(
c.TYPE = 'TYPE_B' AND c.REQUEST_ID IN
(
SELECT d.ID FROM TABLE_D d
WHERE d.REQUEST_ID = 1234 AND v.TYPE = 'TYPE_A'
)
)
)
or is there a better option?
Both queries seem to run about the same time (<50ms) but that may depend on the resulting data. I would need to test more to know for sure.
The point of these two queries is for one of them to replace three other queries where their resulting data is processed in Java to get the required data.
I will also have to be able to convert the SQL query to HQL. I was struggling to convert the first query.
I have a feeling that I maybe wasting my time since the java objects for tables B and C are a one-to-many relationship in the object for table A and they are load by hibernate anyway. Meaning I may not be saving anytime in the long run. Is my thinking here correct?
Thanks!
If I understand correctly, exists would be the best solution:
SELECT a.*
FROM TABLE_A a
WHERE EXISTS (SELECT 1
FROM TABLE_B b
WHERE a.ID = b.FK_ID AND b.REQUEST_ID = 1234 AND b.TYPE = 'TYPE_A'
) OR
EXISTS (SELECT 1
FROM TABLE_C c JOIN
TABLE_D d
ON c.DATA_RQST_ID = d.ID
WHERE a.ID = c.FK_ID AND
c.REQUEST_ID = 1234 AND
(c.TYPE IN ('TYPE_A', 'TYPE_B'))
);
One big gain is just in removing the select distinct.
Then for performance, you want indexes on table_b(fk_id, request_id, type_id) and table_c(fk_id, request_id, type, DATA_RQST_ID) and table_d(id).

How can I JOIN multiple table columns in jpa and jpql

I'm new with JPA and JPQL. I'm trying to query a database grab rows from a table that contains mostly index's of the names contained in other tables.
This is the query in mysql that I'm trying to recreate:
SELECT COUNT(*) as PieceCount,
shifttimes.shiftid as ShiftId,
specienames.NameText as SpecieName,
gradenames.NameText as Grade,
DryerNum,
CreatedLocal
from sheets, shifttimes, specienames, gradenames
WHERE sheets.ShiftIndex = shifttimes.ShiftIndex AND
sheets.SpecieNameIndex = specienames.NameIndex AND
sheets.gradenameindex = gradenames.NameIndex AND
CreatedLocal >= '" . $begin . $StartGraveyard
' AND CreatedLocal < '" . $end . $StartGraveyard
GROUP BY ShiftId, SpecieName, Grade, DryerNum;
This is the query I have and as far as I've gotten:
SELECT COUNT(s.createdLocal),
g.nameText gName,
p.nameText pName
FROM Sheets s , GradeNames g , SpecieNames p
JOIN s.gradeNameIndex gIndex ,
JOIN s.specieNameIndex pIndex
WHERE gIndex = g.nameIndex AND
pIndex = p.nameIndex
GROUP BY gName , pName
This is the Java Glassfish error that I am receiving:
java.lang.IllegalArgumentException: An exception occurred while creating a query in EntityManager:
Exception Description: Syntax error parsing [SELECT COUNT(s.createdLocal), g.nameText, p.nameText FROM Sheets s , GradeNames g , SpecieNames p JOIN s.gradeNameIndex gIndex , JOIN s.specieNameIndex pIndex WHERE gIndex = g.nameIndex AND pIndex = p.nameIndex GROUP BY g.nameText , p.nameText].
[128, 128] The range variable declaration must be specified.
First off all, sorry, but this is not an answer but BIG comment...
You should better stop using this syntax FROM Sheets s , GradeNames g , SpecieNames p.
All tables you need should be properly JOINed by ON clause.
Any JOIN statement should have ON clause and should not have , any comma at the end.
If I understood your 2nd query correctly it must be something like:
SELECT COUNT(s.createdLocal),
g.nameText gName,
p.nameText pName
FROM Sheets s
JOIN GradeNames g
ON s.gradeNameIndex = g.nameIndex
JOIN SpecieNames p
ON s.specieNameIndex = p.nameIndex
GROUP BY gName , pName

complicated sql query returning empty result

My database looks like this
tickets table
-------------
ticket_id
title
description
department_id
status_id
priority_id
assignee_id
creator_id
departments table
------------------
dep_id
dep_name
status table
------------
status_id
status_name
priority table
---------------
pr_id
pr_name
users table
-----------
u_id
username
password
salt
email
firstName
lastName
department_id
userlevel_id
userlevels table
-----------------
ul_id
ul_name
I need to load all tickets given the asignee id. My query looks like this
SQLQuery q = q.createSQLQuery("SELECT t.*,d.*,s.*,p.*,u.*,a.* FROM tickets t, departments d, status s, priority p, users u, attachments a WHERE t.department_id=d.dep_id AND t.status_id=s.stat_id AND t.priority_id=p.pr_id AND t.assignee_id=u.u_id AND t.creator_id=u.u_id AND t.tick_id=a.ticket_id AND assignee_id=?");
q.setInt(0, some_valid_assignee_id);
List<Object> result = q.list();
But it's returning an empty object list. Can anyone point me in the right direction, thanks!!
In your query you have AND t.assignee_id = u.u_idand also AND t.creator_id = u.u_id. The only way that would return any records is if the assignee_id and creator_id were the same. I think what you really need to do is link to the users table twice like so:
SELECT t.*, d.*, s.*, p.*, u1.*, u2.*, a.*
FROM tickets t
INNER JOIN departments d ON t.department_id = d.dep_id
INNER JOIN status s ON t.status_id = s.stat_id
INNER JOIN priority p ON t.priority_id = p.pr_id
INNER JOIN users u1 ON t.assignee_id = u.u_id
INNER JOIN users u2 ON t.creator_id = u.u_id
INNER JOIN attachments a ON t.tick_id = a.ticket_id
WHERE assignee_id = ?
You should use proper join syntax . . . makes the query easier to read and to write.
However, I'm guessing that the problem is:
t.assignee_id = u.u_id AND t.creator_id = u.u_id
That would assume that
t.assignee_id = t.creator_id
Perhaps this never happens in your data.

Categories