I have two column one column associated with another...
Table:base_data
id |---name----|-----des
1 | some name1 | The description1
2 | some name2 | The description2
Table: photos
id |---p_id----|-----photo
1 | 1 | img1s.jpg
2 | 1 | img1w.jpg
3 | 2 | img2.jpg
4 | 2 | img14.jpg
5 | 2 | img15.jpg
I want to select all data from table 1(base_data) and one row from associated row from photos: table how can I do that ????
I don't want to select by greatest n per group I want to select all data from the first table and only one row of the second table which matches with the first table row id, just first match not other.
The Result I want...
id |---name----|---des----|---p_id----|---photo----|
1 | some name |the des..1| 1 | img1s.jpg|
2 | some name |the des..2| 2 | img2.jpg|
I suppose you want to associate base_data with the first photo taken, which should be the one with the lowest photos.id. In MySQL, you could write this as follows: Create an intermediate query which gives - for any p_id - the corresponding record with the lowest id. Then, left join base_data with this intermediate query result. Hope there are not to many typos in it :-) :
select b.id, p2.photo
from base_data b left join
(select p.photo, p.p_id, min(id) from photos p group by p.p_id) p2 on b.id = p2.p_id
If you want the alphanumerically lowest photo name, in MySQL you can do this:
select
t1.*,
t2.photo
from
base_data as t1
left join (
select
p_id,
min(photo) as photo
from
photos
group by
p_id
) as t2 on t2.p_id = t1.id;
Related
I want to get the last activity of my client but i dont know how to that that with two tables that have more than one pivot. Please look at to the example below :
table product
--------------------------------------------------------------------------------------------------------------------------------------
id | name | check_mo (Activity1) | check_mo_account_id | check_pa (Activity2) | check_pa_account_id
--------------------------------------------------------------------------------------------------------------------------------------------
1 | product1 | 01/02/2020 | 63 | 05/02/2020 | 100
2 | product2 | 01/03/2020 | 23 | 10/03/2020 | 63
-----------------------------------------------------------------------------------------------------------------------------------
Table account
--------------------------------
id | name
--------------------------------
23 | name1
63 | name2
100 | name3
--------------------------------
I want this result (last activity is the lastest date of (check_mo and check_pa). and relationship between tables is (account.id => product.check_mo_account_id and product.check_pa_account_id))
------------------------------------------------
id | name | last activity
-------------------------------------------------
23 | name1 | 01/03/2020
63 | name2 | 10/03/2020
100 | name3 | 05/02/2020
-------------------------------------------------
Unpivot the columns. In MySQL, you can use union all. Use join to bring in the names and then a window function to get the most recent date:
select pn.*
from (select pn.*, max(dte) over (partition by name) as max_dte
from ((select n.name, p.check_mo as dte, p.check_mo_account_id as account_id
from product p join
name n
on p.check_mo_account_id = n.id
) union all
(select n.name, p.check_pa, p.check_pa_account_id as account_id, p.check_pa
from product p join
name n
on p.check_mo_account_id = n.id
)
) pn
) pn
where dte = max_dte;
If I understand correctly, you have two check IDs and two check dates in one row, but want to treat them equally, just as if you had just one table with one check ID and one check date per row. Use UNION ALL to get this table. Then find the maximum date per ID and join this to the account table.
select id, account.name, aggregated.last_activity
from account
join
(
select id, max(check) as last_activity
from
(
select check_mo_account_id as id, check_mo as check from product
union all
select check_pa_account_id as id, check_pa as check from product
) unioned
group by id
) aggregated using (id)
order by id;
I have two tables
tbl_groups:
id | name
----------------
1 | BSCS
2 | BSIT
3 | BBA
tbl_students:
id | name | group_id
-------------------------------
1 | Student Name | 1
2 | Student 2 | 1
3 | Student 3 | 2
I want to show groups details: group name and number of students in a particular group,
I am using this query but it shows groups that has students. it does not show group with 0 students.
select tb2.id, tb2.name, count(*) from tbl_students tb1 JOIN tbl_groups tb2 ON tb1.group_id = tb2.id
How do I show all groups, please give me some idea
EDIT:
if I use above query I get following result:
id | name | count(*)
-------------------------------
1 | Student Name | 2
2 | BSIT | 1
(it doest show 3rd group because there are 0 students, I want to show this groups also).
Just use a left join:
select tb2.id, tb2.name, count(tb1.id) as no_std
from tbl_groups tb2
LEFT JOIN tbl_students tb1 ON tb2.id = tb1.group_id
group by tb2.id, tb2.name
See it working live here: http://sqlfiddle.com/#!9/2282a3/5
I would just use a correlated subquery to get the count of students in each group, like so:
select
g.*,
(select count(*) from tbl_students s where s.group_id = g.id) no_students
from tbl_groups g
This does not filter out groups that have no students (it will give a count of 0 instead). And with an index on tbl_students(group_id), this should be as efficient as it gets (this index is already there if you set up a foreign key constraint on that column - as you should have).
I don't exactly know how to word this question correctly, so I'll start with the data because I think it will make more sense that way.
Starting with these two tables:
Table 1:
user_id | equipment_id
------ | ------
1 | 2
1 | 3
1 | 6
2 | 2
2 | 6
Table 2:
equipment_id | exercise_id
------ | ------
2 | 1
3 | 2
6 | 2
I would like to create this third table:
Table 3:
user_id | exercise_id
------ | ------
1 | 1
1 | 2
2 | 1
It seems like a simple INNER JOIN to get the data, but I'm running into trouble with the second row. I only want that row to show up if user_id 1 has both pieces of equipment listed in Table 2. If either piece of equipment is missing, I don't want the data inserted as shown by user_id 2. I also want to make sure I don't get two instances of user_id 1 for each piece of equipment.
This is the code I have so far:
INSERT INTO Table3 (user_id, exercise_id)
SELECT user_id, exercise_id
FROM Table1
INNER JOIN Table2
ON Table2.equipment_id = Table1.equipment_id
The result I get is this with the rows that need to be removed indicated:
Table 3:
user_id | exercise_id
------ | ------
1 | 1
1 | 2
1 | 2 <--- duplicate of row above
2 | 1
2 | 2 <--- user 2 doesn't have equipment 3, so shouldn't be included
Any help on limiting the results would be greatly appreciated. Thank you!
If I understand correctly, you want to retrieve all the exercises for a user where all the equipment required for that exercise is "available" to the user. I've put some code over at rextester.com/AYRE74108. The important part of that looks like this:
select distinct
t1.user_id,
t2.exercise_id
from
table_1 t1
JOIN table_2 t2 ON
t1.equipment_id = t2.equipment_id
where
not exists
(select 1
from
table_2 t2b
where
t2b.exercise_id = t2.exercise_id
AND not exists (select 1
from
table_1 t1b
where
t2b.equipment_id = t1b.equipment_id
AND t1.user_id = t1b.user_id)
)
To explain the logic: I begin with the standard join and distinct. But then I require that there NOT EXIST any piece of equipment required for the exercise such that that user/equipment combination does NOT EXIST. This is equivalent to saying the user has to have "available" (listed in table 1) all the equipment required for the exercise.
Or schematically: "ALL X are Y" === "NO X is such that Not Y".
I feel that the last row of your output should not be 2 | 2 but 1 | 2.
Also using distinct will ensure that there will be no duplicate rows.
SELECT DISTINCT user_id, exercise_id
FROM Table1
INNER JOIN Table2
ON Table2.equipment_id = Table1.equipment_id
Edit - The mistake in the question threw me off. This should work.
SELECT user_id, table2.exercise_id , sum(table2.equipment_id), sum(b.equipment_id)
FROM Table1
INNER JOIN Table2
ON Table2.equipment_id = Table1.equipment_id
inner join table2 as b
on table2.exercise_id = b.exercise_id
group by user_id, table2.exercise_id
having sum(table2.equipment_id)= sum(b.equipment_id)
I have the following MySQL DB structure:
table sales_order - id, name, ...
id | name
------------------
1 | Order Test
table sales_order_item - id, order_id, name, amount_dispatched ...
id | order_id | name | amount_dispatched
------------------------------------------
1 | 1 | Item 1 | 5
2 | 1 | Item 2 | 10
table sales_order_item_invoice - id, item_id, amount, ...
id | item_id | amount
---------------------
1 | 1 | 3
2 | 2 | 5
3 | 2 | 5
These three tables are in chain via the foreign keys. Table "invoice" can have more rows for one row in "item". Table "item" can have more rows for one row in "order".
Now, I need to create SQL query that returns all rows from table sales_order and appends there some data from the other tables - amount_dispatched and amount_invoiced:
dispatched = sum of all order's items' amount_dispatched
invoiced = sum of all invoices' amount (or 0 if no invoice exists)
Such query seems to be straightforward:
SELECT
`sales_order`.*,
SUM(`sales_order_item`.`amount_dispatched`) AS dispatched,
SUM(`sales_order_item_invoice`.`amount`) AS invoiced,
FROM `sales_order`
LEFT JOIN `sales_order_item` ON `sales_order`.`id` = `sales_order_item`.`order_id`
LEFT JOIN `sales_order_item_invoice` ON `sales_order_item`.`id` =`sales_order_item_invoice`.`item_id`
GROUP BY `sales_order`.`id`
The result contains all orders - ok
The result contains sum of invoices amount - ok
The result of "amount_dispatched" is invalid - if the item has more rows in item_invoice, the item's amount is summed several times, so for the example above, I get:
id | name | dispatched | invoiced
---------------------------------------
1 | Order Test | 25 | 13
Amount_dispatched is 25, but I would expect it to be 15.
Any idea how to correct my SQL query?
Thank you.
Firstly, use subquery do aggregation for invoice amount in sales_order_item_invoice, then left join.
SELECT
`sales_order`.*,
SUM(`sales_order_item`.`amount_dispatched`) AS dispatched,
SUM(t.`amount`) AS invoiced
FROM `sales_order`
LEFT JOIN `sales_order_item` ON `sales_order`.`id` = `sales_order_item`.`order_id`
LEFT JOIN (
SELECT item_id, SUM(amount) AS amount
FROM `sales_order_item_invoice`
GROUP BY item_id
) t ON `sales_order_item`.`id` = t.`item_id`
GROUP BY `sales_order`.`id`
I have a table that contains all the distinct names from another table, and then a column that holds the minimum value that the name received. For example, the table looks like this:
table1
Name | min_value
a | 1
b | 2
c | 4
The original table looks like this:
table2
Name | value
a | 1
b | 2
c | 4
a | 2
c | 8
a | 1
I want to return the number of times that the minimum value occurs within the original table. So, in this example it would return something like this:
output_table
Name | times_at_min
a | 2
b | 1
c | 1
Any help would be appreciated, thanks in advance.
One way to do it is:
SELECT m.Name,
min_value,
COUNT(CASE WHEN m.value = min_value THEN 1 END) As times_at_min
FROM mytable AS m
INNER JOIN (
SELECT Name,
MIN(value) AS min_value
FROM mytable
GROUP BY Name ) AS g
ON m.Name = g.Name
GROUP BY Name
In a subquery you select MIN(value) per Name. Joining with the derived table of this subquery, you can perform conditional aggregation so as to calculate the number of times the minimum value appears in the original table.
Fiddle demo here