how to get the sum of a child column from another table - mysql

i have a system that can get member information. i want my system to automatically get the name of the awardee. The conditions are if the member have recruited 6 people, he/she sold 15 soaps and his/her downlines sold 15 soaps each. Im using mysql and VB.NET so far i have this query.
SELECT *
FROM members m
LEFT JOIN
geneology g
ON SUM(m.status) >=90 AND
m.upline = g.parent_id;
but i get
1111 error - invalid use of group function
Table 1 has columns
id, name, status 'This is where the soap data are stored', downlines, upline
Table 2 has columns
id, parent_id, child_id
Please help im new to sql queries

First of all, the ON clause defines the criteria used to match the rows of the two tables, so that SUM() >= 90 is not supposed to stay there (in fact, that's why you're getting that error).
I will assume that for a person on table members, upline is the ID of the member that recruited him/her. If that's correct, you can build your query like this:
select t1.id, t1.name
from members t1
join geneology t2
on t1.id = t2.parent_id
join members t3
on t2.child_id = t3.upline
where t1.status = 15
group by t1.id, t1.name
having count(distinct t3.id) = 6 and
sum(t3.status) = 90
This will use the members table twice, once for the parent and once for the children, and the two tables are correlated by the geneology table.
The condition in the where clause is for the parent, then you group the child data for each parent, and only return the parents whose children satisfiy the conditions in the having clause.

Related

How to Merge Two Select Query in Mysql

I have below table structure in my users table where user and driver are saved with a unique id and separated with user_type column. user ratings are being saved in rider_avg_ratings column and driver ratings are being saved in driver_avg_ratings column.
when a user submit a request it is being saved in requesttable with both userid and nearby driver id. now I have to return both driver ratings and user ratings from users table in a single query.Problem is when I join request.userid=users.id it is returning rider_avg_ratings to get the driver_avg_ratings i need to join users.id=request.driver_id how can I get both user and driver ratings from a single query
From above two table by joinning request.user_id=users.id I need to return driver_avg_ratings=4.38 and rider_avg_ratings=1.25
SELECT r.user_id as userId, u.rider_avg_ratings as ratings
FROM user as u
INNER JOIN request as r on u.id = r.user_id
UNION
SELECT r1.driver_id as userId, u1.driver_avg_ratings as ratings
FROM user as u1
INNER JOIN request as r1 on u1.id = r1.driver_id
This query will fetch the desired result.
Your union query should produce a The used SELECT statements have a different number of columns error. You need to figure out why your code isn't checking for errors and make it do so. Also, if this is the entire statement, the parentheses around it don't belong.
You need to make the two unioned selects return the same number of parameters. Note that as in the second select's select columns will be ignored and result column names will come from the first select only. Minimally, to make the query run, you would need to add ,NULL,NULL,... to your second select, but it seems likely you want more information to be able to identify which user the driver_avg_ratings is for, like the id, name, etc the first query is returning.
It's often helpful when processing the results to add something indicating which select a row came from, too, e.g. SELECT "pending_request_users" AS type, ... UNION ALL SELECT "all_users_avg_rating", ....
Note that the different SELECTs unioned together return entire rows. If your only goal is to add driver ratings to the rows already returned, you don't want a union, you may just want to add:
SELECT ..., driver.driver_avg_ratings
FROM user u
...
INNER JOIN user AS driver ON driver.id=req.driver_id
(or left join if there may not be a driver_id). But it's hard to tell for sure if that's what you want. Provide sample data and your desired results from it. In any case, do make your code detect errors properly.
for example:
Department
1 A
2 B
3 A
4 C
5 B
6 D
7 E
8 F
You could do something like
SELECT
1 AS Deptnumber
, Dept
FROM tbl_students
WHERE Dept IN ('A', 'B', 'C')
UNION
SELECT
2 AS DeptNumber
, Dept
FROM tbl_students
WHERE Dept IN ('D', 'E')
UNION
SELECT
3 AS Deptnumber
, Dept
FROM tbl_students
WHERE Dept IN ('F')

MySQL Differences with counts caused by joins

i have a problem in MySQL where I use the COUNT function for conditions. However, when combining this with joins, although I use grouping, the COUNT values include ALL rows, even the ones filtered out.
I'm providing a minimal working example, which however maybe does not make a practical sense or is designed smartly.
So assume I have 3 tables:
products with fields: productId, name, active (boolean)
teams with fields: teamId, name
rel_production with fields: teamId, productId
So basically I have products and teams with ids and names. Products can be active (lets say that means that they are still in production or so).
And then I have a relation which team is working on which product.
To explain my problem, assume the following minimal amount of data to clarify the problem is contained inside the tables:
products
teams
rel_production
Now the query that I want to do is, in plain english: "I want all teams that are working on exactly 2 products while atleast one product must be active."
The query in general works and is the following in mysql:
SELECT
teams.*,
"r_count:",
r_count.*,
COUNT(r_count.productId),
"r_active:",
r_active.*,
"p_active:",
p_active.*
FROM teams
INNER JOIN rel_production r_active ON r_active.teamId = teams.teamId
INNER JOIN products p_active ON p_active.productId = r_active.productId AND p_active.active
INNER JOIN rel_production r_count ON r_count.teamId = teams.teamId
GROUP BY teams.teamId, r_active.teamId
HAVING COUNT(r_count.productId) = 2 #4 is the problem!!!!!!!!!!!!!
Now them problem is with team 1. Because it is working on 2 active products, COUNT(r_count.productId) will be 4 and not 2. So my query will filter it out.
Here is the screenshot with the result without the HAVING clause:
I see why this happens, because the two inner joins on rel_production will cause 4 rows to be generated. But then they are merged always together to one using the GROUP BY. So what I need is the COUNT after the GROUP and not before.
How can I fix this?
Perform the filtering on teams in a separate subquery, and then join to that:
SELECT
t1.teamId,
t1.name
FROM teams t1
INNER JOIN
(
SELECT t1.teamId
FROM rel_production t1
INNER JOIN products t2
ON t1.productId = t2.productId
GROUP BY t1.teamId
HAVING COUNT(DISTINCT t1.productId) = 2 AND SUM(t2.active) > 0
) t2
ON t1.teamId = t2.teamId;
SQLFiddle

How can I select data from one table depending on the data from another table

I have 2 tables: contracts_main_list and contracts_detail.
In contracts_main_list I have columns:
user_id
contract_id
and in contracts_detail:
contract_id
other columns with data
I need to select all the rows from the table contracts_main_list WHERE user_id = some number.
From these rows I need to get the list of contract numbers (from column contract_id) and according to them select rows corresponding to each of the contract number from the list. So something like:
WHERE contracts_detail.contract_id = contracts_main_list.contract_id
The contract_ids are probably gonna be unique, but in case there is some kind of error and there will be more rows with the same contract_id in either of the tables, I need to select only one row (so probably using DISTINCT) and select the latest record (both tables have a column id as a primary key)
Also if there is no row in contracts_detail matching with the contract_id to the contract_id of the first table contracts_main_list it should skip the row. But I guess the condition:
WHERE contracts_detail.contract_id = contracts_main_list.contract_id
already covers it.
I hope I made it clear enough. What I am trying to do in real life is show list of contracts with all the relevant data belonging to the user.
To sum this up, I need to find all the contracts belonging to the user and select the rows with details about each contract and finally get the data from the contracts_detail table as a result.
Here is the result you're looking for:
SELECT CD.*
FROM (SELECT C2.contract_id
,MAX(C2.id) AS last_main_list_id
,MAX(CD2.id) AS last_contracts_detail_id
FROM contracts_main_list C2
INNER JOIN contracts_detail CD2 ON CD2.contract_id = C2.contract_id
GROUP BY C2.contract_id) L
INNER JOIN contracts_main_list C ON C.id = L.last_main_list_id
AND C.user_id = ?
INNER JOIN contracts_detail CD ON CD.id= L.last_contracts_detail_id
This query use a subquery for the FROM because of the following indication you provided:
The contract_ids are probably gonna be unique, but in case there is
some kind of error and there will be more rows with the same
contract_id in either of the tables, I need to select only one row
If you're sure that the contract_id are unique, here is the same query without this check on contract_id:
SELECT CD.*
FROM contracts_main_list C
INNER JOIN contracts_detail CD ON CD.contract_id = C.contract_id
WHERE C.user_id = ?
Hope this will help you.

MySQL join on max value

From joining the tables below on the entry.id, I want to extract the rows from the food_brands table which have the highest type_id - so I should be getting the top 3 rows below, with type_id 11940
food_brands
id brand type_id
15375 cesar 11940
15374 brunos 11940
15373 butchers 11940
15372 bakers 11939
15371 asda 11939
15370 aldi 11939
types
id type quantity food_id
11940 comm 53453 10497
11939 comm 999 10496
foods
id frequency entry_id
10497 twice 12230
10496 twice 12230
10495 once 12230
entries
id number
12230 26
My attempt at the query isn't filtering out the lower type.id records - so from the table records below in food_brands, i'm getting those with type_id 11940 and 11939. Grateful for any help fix this!
SELECT fb.*
FROM food_brands fb
INNER JOIN types t ON fb.type_id = t.id
INNER JOIN
(
SELECT MAX(id) AS MaxID
FROM types
GROUP BY id
) t2 ON t.food_id = t2.food_id AND t.id = t2.MaxID
INNER JOIN foods f ON t.food_id = f.id
INNER JOIN entries e ON f.entry_id = e.id
WHERE entries.id = 12230
A simple subquery should do it just fine;
SELECT * FROM food_brands WHERE type_id=
(SELECT MAX(t.id) tid FROM types t
JOIN foods f ON f.id=t.food_id AND f.entry_id=12230)
An SQLfiddle to test with.
If you just want to return the rows from food_brands with the max type id, you should be able to use:
SELECT fb.*
FROM food_brands fb
INNER JOIN
(
select max(id) id
from types
) t
on fb.type_id = t.id
See SQL Fiddle with Demo
I don't know why you are doing all these inner joins after the one on the t2 subquery, since you are only retrieving the columns of fb, but I suppose that you are not showing the whole query, and you just want to get that one fixed.
The issue is actually in the subquery t2: there, for some untold reason, you choose to do a GROUP BY id which changes the MAX function semantic to generate a maximum value per id, and since you are asking the maximum on that very column, MAX and GROUP BY cancel out each other. Just removing the GROUP BY clause fixes the query.
If for some untold reason you cannot remove that clause, perhaps replacing MAX(id) by id and adding ORDER BY id DESC LIMIT 1 would do.
Also, your subquery should probably select also food_id since it is used in the subsequent INNER JOIN clause.

mysql query on database using composite design pattern

I'm not an SQL expert and therefore am having trouble wrapping my head around designing a mysql query to query database tables designed using the "composite design pattern."
The tables are:
composites:
id, name, type [type is either "Condition" or "ConditionGroup"]
composites_properties:
id, composite_id, property_id
groupings:
id, parent_id, child_id
properties: id, key, value
What I want to do is generate a query that will return the unique properties of the group's ("ConditionGroup") member conditions ("Condition") such that I end up with a Group Name and a list of Property Keys (inherited from the member conditions).
The best I've come up with is:
SELECT DISTINCT properties.`key`, composites.name
FROM composites, composites_properties, properties
WHERE composites.id=composites_properties.composite_id
AND properties.id=composites_properties.property_id
AND composites.id IN (
SELECT child_id FROM groupings WHERE parent_id IN
(SELECT id FROM composites WHERE type='ConditionGroup')
)
This yields each member condition along with its list of properties where the properties are repeated if more than one member condition has that property.
In the end I'd like:
Group Name
property_1
property_2
property_3
But I'm getting the following type list (with no indication to which group the conditions belong)
Condition Name 1 property_1
Condition Name 1 property_2
Condition Name 1 property_3
Condition Name 2 property_1
Condition Name 2 property_2
Condition Name 3 property_1
Condition Name 3 property_2
Any suggestions?
To be honest, I'm a little unclear on exactly what you are trying to accomplish, but I'll give it a shot. If you can clarify how this query does not do what you want, I can probably help further.
SELECT c.name, p.key
FROM composites c
INNER JOIN groupings g ON c.id = g.parent_id
INNER JOIN composites_properties cp ON cp.composite_id = g.child_id
INNER JOIN properties p ON p.id = cp.property_id
WHERE c.type = 'ConditionGroup'
This doesn't seem like the best query in the world to me because it ignores what the children in each grouping actually are, so I'm not sure this is what you want.