I'm almost new with SQL syntax and I need help to create a view on MySQL.
I have a table with a PK column called ID, a column called total_seats and another one is title.
In the second table, I have multiple rows, with a firstname column and a FK that corresponds to the PK (total_seats) present in the first table.
I need to create a view where I can calculate the available_seats (total_seats minus occurrence in the second table) for each element present in the first table.
Actually I'm calculating the "occupied" seats but the join give me the result only for already taken event, so the result is that I don't see the available_seats for the empty event.
SELECT b.ID_event, a.*,
COUNT(*) AS occupied FROM second_table b
LEFT JOIN first_table a ON b.ID_event = a.ID
GROUP BY ID_event
You could subtract the count
select a.ID_event, a.total_seats, count(*) as occupied, a.total_seats - count(*) difference
from first_table a
left join second_table ba ON b.ID_event = a.ID
group by a.ID_event, a.total_seats
Related
So I have the "main" table (A) with fields: id, order_number, order_name and table (B) with fields: id, fk.order_number, tracking_number
Table (A) is responsible for keeping track of each order, while table (B) stores all associated tracking information per each order.
What I am trying to accomplish is to query each order from table A and join table B to show the first tracking number that has been stored for each order, almost like a limit 1 (return only the first stored tracking number for each order).
How I am doing this currently is a join between table A and table B on the order_number field, but I am using the GROUP BY tableA.order_number at the end of the statement.
select tablea.order_number, tablea.order_name, tableb.tracking_number
from tablea
join table b
on tablea.order_number = tableb.order_number
group by tablea.order_number
I guess the question revolves around, what is the default group by ordering when you return multiple rows back from the joined table?
For example, in table A, there is only 1 row, while in tale B there are 2 rows (2 tracking numbers for the order). So, when I group by in this case, does that always take the first match from the joined table where the condition matches the group by? If I removed group by, 2 rows would be returned.
I realize what is happening because I have the group by condition on tableA, and so it only shows the first row because both rows returned from the join have the same order number, which appears to be what I want (limit 1 tracking number per order), but I'm not sure if programmatically I actually did this correctly or if it happens this way because that is how the group by clause works and how I used it here. I just want to limit 1 tracking number from the tableB based on the order_number of table A.
Updated (with example query)
SELECT m.message_id, m.message_date, m.message_order_number, m.message_purchase_order, m.message_vendor_invoice, ve.vendor_email_display, concat(c.customer_first_name, ' ', c.customer_last_name) as customer_name,
min(ti.tracking_information_id) as tracking_information_id, ti.tracking_information_tracking_number, ti.tracking_information_tracking_number_status
FROM email.message m
JOIN email.customer c
ON m.message_tagged_customer_first = c.customer_id and m.message_tagged_customer_last = c.customer_id
JOIN vendor_email ve
ON m.message_sender = ve.vendor_email_id
LEFT JOIN tracking_information ti
ON m.message_order_number = ti.tracking_information_order_number
group by m.message_order_number
In this case, I want to return all information in message table, and the first matching row in table tracking
Group byis for aggregation function as MIN() ,, MAX() , COUNT() . .. and is for define respect which column the aggreagtion function must be performed..
If you are looking for a specific ordered result you should use ORDER BY that work for the columns value as is
select tablea.order_number, tablea.order_name, tableb.tracking_number
from tablea
join table b on tablea.order_number = tableb.order_number
order by tablea.order_number
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.
I've been trying to make this work properly for a while now but just can't get my head around how to go about it, hopefully someone here can help me!
I have three tables:
Table A
Table B
Table C
I want to get the top 10 results from Table A based on a ranking that will depend on information from table B and table C. The ranking will be using the following formula:
Ranking = (COUNT(id)
from table C
WHERE c.a_id = a.id) as count_weight +
(COUNT(id)
FROM table B
WHERE b.a_id = a.id)*(count_weight*0.25) + a.views
In words I want the ranking to be equal to a point value determined by:
The count of records in Table C that correspond to the record in Table A that I'm interested in
If a record exists in Table B that corresponds to the record in Table A I'm interested in, I want an additional increase in the points by 25% (taking the points gained from #1 and multiply by 0.25) - In this case a record will exist or wont exist so it will always be 0 or 1
Points for each "view" for the record in Table A (a field of table A)
Hopefully I worded that in a understandable manner!
Thanks!
I think this is what you're after:
SELECT a.*, COUNT(c.id) * IF(COUNT(b.id),1.25,1) + a.views AS Ranking
FROM a LEFT JOIN c ON a.id = c.a_id LEFT JOIN b ON a.id = b.a_id
GROUP BY a.id
ORDER BY Ranking DESC
LIMIT 10
If you don't want to select the Ranking, you can put that column's formula directly into the ORDER BY clause.
I have 2 tables, the first one is MASTER_TABLE with fields ID, STATUS_CODE, STATUS_SUBCODE, SUBJECT_CODE, SUBJECT_SUBCODE and the second table is CODE_TABLE which has the unique description for every combination of a code and subcode. It has the following fields CODE, SUBCODE and DESCRIPTION
How to write a query to retrieve the ID, STATUS and SUBJECT , for example for every combination of STATUS_CODE and STATUS_SUBCODE in MASTER_TABLE I have to get the STATUS value in CODE_TABLE, similarly I have to do the same thing for SUBJECT
You must join twice to CODE_TABLE - once for each type of look-up, so to distinguish the rows from eachother, you must alias at least one (but usually one would alias both, as below):
select
mt.ID,
ct1.DESCRIPTION as STATUS
ct2.DESCRIPTION as SUBJECT
from MASTER_TABLE mt
left join CODE_TABLE ct1
on ct1.CODE = mt.STATUS_CODE and ct1.SUBCODE = mt.STATUS_SUBCODE
left join CODE_TABLE ct2
on ct2.CODE = mt.SUBJECT_CODE and ct2.SUBCODE = mt.SUBJECT_SUBCODE
I have made the joins left joins in case data is missing from CODE_TABLE, in which case this query would produce a null for the corresponding description.
I have 2 tables authors and authors_sales
The table authors_sales is updated each hour so is huge.
What I need is to create a ranking, for that I need to join both tables (authors has all the author data while authors_sales has just sales numbers)
How can I create a final table with the ranking of authors ordering it by sales?
The common key is the: authorId
I tried with LEFT JOIN but I must be doing something wrong because I get all the authors_sales table, not just the last.
Any tip in the right direction much appreciated
If you're looking for aggregate data of the sales, you'd want to join the tables, group by the authorId. Something like...
select authors.author_id, SUM(author_sales.sale_amt) as total_sales
from authors
inner join author_sales on author_sales.author_id = authors.author_id
group by authors.author_id
order by total_sales desc
However (I couldn't distinguish from your question whether the above scenario or next is true), if you're only looking for the max value of the author_sales table (if the data in this table is already aggregated), you can join on a nested query for author_sales, such as...
select author.author_id, t.sales from authors
inner join
(select top 1 author_sales.author_id,
author_sales.sale_amt,
author_sales.some_identifier
from author_sales order by some_identifier desc) t
on t.author_id = author.author_id
order by t.sales desc
The some_identifier would be how you determine which record is the most recent for author_sales, whether it is a timestamp of when it was inserted or an incremental primary key, however it is set up. Depending on if the data in author_sales is aggregated already, one of these two should do it for you...
select a.*, sum(b.sales)
from authors as a
inner join authors_sales as b
using authorId
group by b.authorId
order by sum(b.sales) desc;
/* assuming column sales = total for each row in authors_sales */