(another) LEFT JOIN issue with ACCESS - ms-access

I want summary data from my 'Data' table for all companies in 'Companies' table including blank rows where there is no record in Data.
If I summarise the data in a nested SELECT clause (or in a stored query i get nothing from the data table. For example
This is the sub select
SELECT transco,
sum(m1) AS Jan15,
FROM data
WHERE (QVmeasure = 'Vol')
GROUP BY QVmeasure, transco
which outputs:
transco Jan15
0292 154373665
1419 134915098
If I use it in a sub select as follows
SELECT c.SAP_Code,
Jan15
FROM Companies AS c
LEFT JOIN (
SELECT transco,
sum(m1) as Jan15
FROM data
WHERE (QVmeasure = 'Vol')
GROUP BY QVmeasure, transco)
AS d
ON c.SAP_Code = d.transco
I get:
SAP_Code Jan15
0292
1419
I can get the correct result via a temporary table:
SELECT sum(m1) as Jan15,
transco
INTO Temp_Table
FROM data
WHERE (QVmeasure = 'Vol')
GROUP BY QVmeasure, transco
followed by
Select c.SAP_code,
jan15
FROM companies AS c
LEFT JOIN Temp_Table as i
ON (c.SAP_Code = i.transco)
giving:
SAP_code jan15
0292 154373665
1419 134915098
1423
but if I use temporary tables I will have to create macros and i want users to be able to run just a query.
The following works for this simple case but I can't apply it in other circumstances:
SELECT c.SAP_Code,
sum(m1) AS Jan15
FROM Companies AS c
LEFT JOIN data as d
ON c.SAP_Code = d.transco
WHERE (d.QVmeasure = 'Vol') OR (d.QVmeasure is null)
GROUP BY d.QVmeasure,c.sap_code
Is there something wrong with my sub select syntax or is it ACCESS (2013)
TIA

You could nest the sub-query like this:
SELECT c.SAP_Code,
(SELECT sum(d.m1)
FROM data AS d
WHERE d.QVmeasure = 'Vol' AND c.SAP_Code = d.transco
) AS [Jan15]
FROM Companies AS c

Related

MYSQL - CONCATENATE a lookup tables columns into one row

I have the following table structure:
tbl_catalogue_state
In tbl_catalogue there is a part number 58674 that has three states in the tbl_catalogue_state_lk table. Here is the result when I run a query inner joining the three tables.
As expected there are multiple rows returned.
Is there a way to only return one row having the values for each catalgue_state_id on the same row?
I would also like the ability to ignore a row for example:
select tbl_catalogue.catalogue_part, tbl_catalogue_state.catalogue_state_id from tbl_catalogue
inner join tbl_catalogue_state_lk on tbl_catalogue.catalogue_id = tbl_catalogue_state_lk.catalogue_id
inner join tbl_catalogue_state on tbl_catalogue_state_lk.catalogue_state_id = tbl_catalogue_state.catalogue_state_id
where tbl_catalogue_state_lk.catalogue_state_id <> 1;
The above select still returns two rows.
UPDATE
I was able to use GROUP_CONCAT:
select tbl_catalogue.catalogue_part, GROUP_CONCAT(tbl_catalogue_state.catalogue_state_id) as cat_state from tbl_catalogue
inner join tbl_catalogue_state_lk on tbl_catalogue.catalogue_id = tbl_catalogue_state_lk.catalogue_id
inner join tbl_catalogue_state on tbl_catalogue_state_lk.catalogue_state_id = tbl_catalogue_state.catalogue_state_id
where tbl_catalogue_state_lk.catalogue_state_id <> 1
group by tbl_catalogue.catalogue_id;
My issue is the above statement still returns a row. I need it to return nothing.
I was able to use not exists:
select tc.catalogue_part, GROUP_CONCAT(tcs.catalogue_state_id) as cat_state from tbl_catalogue as tc
inner join tbl_catalogue_state_lk as tcsl on tc.catalogue_id = tcsl.catalogue_id
inner join tbl_catalogue_state as tcs on tcsl.catalogue_state_id = tcs.catalogue_state_id
where
not exists
(
select tcsl2.catalogue_state_id from tbl_catalogue_state_lk as tcsl2
where tcsl2.catalogue_state_id = 6 and tcsl2.catalogue_id = tc.catalogue_id
)
and
not exists
(
select tcsl3.catalogue_state_id from tbl_catalogue_state_lk as tcsl3
where tcsl3.catalogue_state_id = 1 and tcsl3.catalogue_id = tc.catalogue_id
)
and
not exists
(
select tcsl3.catalogue_state_id from tbl_catalogue_state_lk as tcsl3
where tcsl3.catalogue_state_id = 2 and tcsl3.catalogue_id = tc.catalogue_id
)
group by tc.catalogue_id;

MySQL query for not exists in another table

I have two MySQL Tables...
1. master_fee
2. fees_receiving_ledger
I do not want to show the FeeId containing FeeFrequencyId : 4 from master_fee table if they are present in fees_receiving_ledger table.
Like above I do not want to show the Admission Fee (FeeId:1) containing FrequencyId : 4 as it is present in fees_receiving_ledger.
I have tried like below...
Select
master_fee.*
From
master_fee
Where Not Exists(Select
fees_receiving_ledger.FeeId
From
fees_receiving_ledger
Where
fees_receiving_ledger.FrequencyId = '4')
My query giving me blank result.
I tried This but failed.
What should be the query ?
I am using VB.NET with MySQL database.
you forgot the join condition in your subselect.
select m.* from master_fee m
where not exists (
select 1 from
fees_receiving_ledger f
where f.frequencyID = 4
and m.feeid=f.feeid)
You could also do:
select m.* from master_fee m left join fees_receiving_ledger f
on f.feeid = m.feeID
where f.frequencyID <> 4;

mysql: Get combination of data from multiple table by passing multiple value

In my DB. I have three tables Category, Location and classification.
I have some value in array for every column
location:['delhi','mumbai','goa','chennai']
Category:['Teacher','Student','Managment']
classification:['expert','normal']
Now I want to fetch the combination of data from the table.
I'm using a stored procedure for this.
Previously I have only one location, one category and one classification so I'm using this:
FROM user u1, serviceprovider s1, city c1
WHERE s1.userId = u1.id
AND c1.cityId = s1.city
AND s1.serviceProviderId IN
(SELECT DISTINCT serviceprovidecategoryr_cl AS serviceProviderId
FROM Db.serviceprovider_cl__serviceproviderclassification_classification t1
INNER JOIN Db.location_servicelocation__serviceprovider_locationid t2 ON t1.serviceprovider_cl = t2.serviceprovider_locationId
INNER JOIN Db.category_serviceprovidercategory__serviceprovider_category t3 ON t2.serviceprovider_locationId = t3.serviceprovider_category
WHERE
t1.serviceproviderclassification_classification IN
(SELECT serviceProviderClassificationId
FROM serviceProviderClassification sp
WHERE sp.name = classification)
AND t2.location_serviceLocation IN
(SELECT locationId
FROM location
WHERE shortAddress = location)
AND t3.category_serviceProviderCategory IN
(SELECT categoryId
FROM category
WHERE categoryName = category)
);
END
but now I'm getting the multiple values so how to modify this stored procedure?
If there is any other good way for doing this.
Please help...

Trying to building optimised Query for Group and Subgroup for a user

i am trying to write the Query for three things .My table structure is like that
You can see Schema at http://sqlfiddle.com/#!2/56c2d/1
I am trying to write the query in MYSQL
user:- table
user_id
user_fname
This is User tabke which will save User Information
group:- "group" and "subgroup" is maintain in same table using column "group_parent_group_id"
group_id
group_title
group_parent_group_id(INT)
This is group table which will save Group and Subgroups
user_group: table
user_group_id
user_group_user_id
user_group_group_id
This ill store both User and Group relation using their Id
I am trying to write the Query for three things. Fetching Users Groups, Subgroups
1) Query to fetch list of All Groups for User Register. Query is gelow and is giving error
Query:
select user.id, user.user_fname, group.group_id, group.group_title
from `user`
inner join user_group on user_group.user_group_user_id = user.user_id
inner join group on group.group_id = user_group.user_group_group_id
where user_group.user_group_user_id = 1 and user_group.group_parent_group_id = 0
2) I am Looking the query to fetch all subgroups(For Whom user is already Register) for Group Id 1,2 or 1
3) I am Looking the query to fetch all subgroups(For Whom user is Not Register yet) for Group Id 1,2 or 1. Ideal is for giving him randomly suggest a subgroup to add
Please Help. I am a newbie in DB :(
Your query is probably failing as you have a table called group, which is a reserved word. You can use back tics to delimit the name to get away with this (as follows) but it would be a better idea to change the table name.
SELECT user.id, user.user_fname, `group`.group_id, `group`.group_title
FROM `user`
INNER JOIN user_group ON user_group.user_group_user_id = user.user_id
INNER JOIN `group` ON `group`.group_id = user_group.user_group_group_id
WHERE user_group.user_group_user_id = 1
AND user_group.group_parent_group_id = 0
EDIT updated for queries I think the OP requires.
First query will get a list of all the groups (ones that have no parent group id) that a user (in this case id 28) is a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
INNER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id
INNER JOIN y2m_group ON y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id = 0
This query will get a list of all the sub groups (ones where the parent group id is greater than 0) that a user (in this case id 28) is a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
INNER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id
INNER JOIN y2m_group ON y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id > 0
This query will get a list of all the sub groups (ones where the parent group id is greater than 0) that a user (in this case id 28) is NOT a member of
SELECT y2m_user.user_id, y2m_user.user_first_name, y2m_group.group_id, y2m_group.group_title
FROM y2m_user
CROSS JOIN y2m_group
LEFT OUTER JOIN y2m_user_group ON y2m_user_group.user_group_user_id = y2m_user.user_id AND y2m_group.group_id = y2m_user_group.user_group_group_id
WHERE y2m_user.user_id = 28
AND y2m_group.group_parent_group_id > 0
AND y2m_user_group.user_group_id IS NULL
Please excuse any typos as not tested (with your test data there are no sub groups).

Is there a way to optimize this update query?

I have a master table called "parent" and a related table called "childs"
Now I run a query against the master table to update some values with the sum from the child table like this.
UPDATE master m SET
quantity1 = (SELECT SUM(quantity1) FROM childs c WHERE c.master_id = m.id),
quantity2 = (SELECT SUM(quantity2) FROM childs c WHERE c.master_id = m.id),
count = (SELECT COUNT(*) FROM childs c WHERE c.master_id = m.id)
WHERE master_id = 666;
Which works as expected but is not a good style because I basically make multiple SELECT querys on the same result. Is there a way to optimize that? (Making a query first and storing the values is not an option.
I tried this:
UPDATE master m SET (quantity1, quantity2, count) = (
SELECT SUM(quantity1), SUM(quantity2), COUNT(*)
FROM childs c WHERE c.master_id = m.id
) WHERE master_id = 666;
but that doesn't work.
Update: Here is the solution, thanks to everbody:
You can do something like this:
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = c.quantity1,
master.count = 1
If you have only one child record at a time. However if you want to use a group function like SUM() in the joined table that doesn't work. Either you get a "Invalid use of group function" if you leave the "group by" part or a "You have an error in your sql syntax if you use "GROUP BY c.master_id"
-- This doesnt work :(
UPDATE master m
INNER JOIN childs c ON m.master_id = c.master_id
SET master.quantity1 = SUM(c.quantity1),
master.count = COUNT(c.*)
GROUP by c.master_id
The solution is to use JOIN with a subquery:
UPDATE master m
INNER JOIN
(
SELECT master_id,
SUM(quantity1) as quantity1,
COUNT(*) as count
FROM childs c
GROUP BY master_id
) c
ON c.master_id = m.master_id
SET m.quantity1 = c.quantity1,
m.count = c.count
WHERE m.master_id = 666;
But since this pulls every row from the childtable the overhead would likely be bigger than using more subqueries like in the original sql. So you should add a WHERE clause to the joined table to get only the rows you need.
Another interesting approach is this syntax, which does the same as the JOIN with the WHERE clause but you should only use if if you want to update all rows with the same values and your subquery only returns one row, since the result from the subquery gets appended to the result and can be used like any column.
UPDATE master m,
(
SELECT SUM(c.quantity1) as sum_of_quantity,
COUNT(*) as rowcount FROM child c WHERE c.master_id = 666
) as c
SET m.quantity1 = c.sum_of_quantity,
m.count = c.rowcount
WHERE m.master_id = 666;
Rewriting Lieven's solution to MySQL:
UPDATE master m
JOIN (
SELECT master_id
, SUM(quantity1) as quantity1
, SUM(quantity2) as quantity2
, COUNT(*) as count
FROM childs c
GROUP BY
master_id
) c
ON c.master_id = m.master_id
SET
m.quantity1 = c.quantity1
,m.quantity2 = c.quantity2
,m.count = c.count
WHERE m.master_id = 666;
I don't know if it is allowed in MySQL, but SQL Server allows you to use the result of a select in an update.
UPDATE master m SET
quantity1 = c.quantity1
, quantity2 = c.quantity2
, count = c.count
FROM master m
INNER JOIN (
SELECT master_id
, quantity1 = SUM(quantity1)
, quantity2 = SUM(quantity2)
, count = COUNT(*)
FROM childs c
WHERE master_id = 666
GROUP BY
master_id
) c ON c.master_id = m.master_id
You could select your data into a temporary table, and then update using that data.
If you also want to insert "new" data in the same roundtrip, look into INSERT INTO ... SELECT FROM ... ON DUPLICATE KEY UPDATE ...
If you already are doing inserts if row doesn't exist, then that would be redundant with this example.
example:
INSERT INTO master m (id, quantity1, quantity2, count)
SELECT master_id, SUM(quantity1) q1, SUM(quantity2) q1, COUNT(*) c
FROM childs
GROUP BY master_id
ON DUPLICATE KEY UPDATE
m.quantity1 = q1,
m.quantity2 = q2,
m.count = c
NOTE! This is untested code, but I think it should be possible to backreference the select result in the UPDATE.
Syntax reference: http://dev.mysql.com/doc/refman/5.0/en/insert.html