I need to create a query from 2 tables, where my company stores e-shop information.
Example of data from the first table:
currentDate: 5.5.2022 | eshopId: 1 | eshopName: test | active: true |
Table 2:
currentDate: 5.5.2022 | eshopId: 1 | orderId: 123 | attribution: direct |
From the first table, I want get how many days in a given period the eshop was active. From the second table, I would like to count all the orders that were attributed directly to our company in the same time period as in the first table.
SELECT i.id, count(*)
from table1 as i
FULL JOIN table1 as e ON e.id= i.id
WHERE i.active = TRUE
GROUP BY i.id
I tried merging the same table twice, because after I used count to get amount of inactive dates, I could not use another variable as it was not aggregated. This still does not work. I cannot imagine how I would do this for 3 tables. Can someone please point me in the right direction on how to do this? Thanks.
If there is one row for each day per eshopId and you want to count number of active days along with number of order per eshopId:
SELECT i.eshopId, count(*)
from table1 as i
left join (select eshopId, count(distinct orderId) from table2 group by eshopId) j on i.eshopId=j.eshopId
WHERE i.active = TRUE
GROUP BY i.eshopId
Related
I have 2 tables. Table A and Table B.
Table A contains the details of individual users.
Table B contains 3 columns, namely "is_completed", "user_id" and "work_id"......
Table B tracks the details of work done by users and whether the work is completed or not. If completed, then that user can be assigned another work.
Problem Statement :
I assigned a work to user 1 and his is_completed is 0 (work not finished)...now I assume that after some days, his work is finished, so I did is_completed as 1 but at the same time I assigned another work to the same user 1 and now is_completed is 0. So I have two rows of same user, one with is_completed as 1 and another is_completed as 0 in Table B.
How can I fetch the latest is_completed i.e. user 1 as working or say busy?
SELECT COUNT(DISTINCT t.work_id) AS working FROM
(
SELECT * FROM
FROM TableB
WHERE user_id = 1
ORDER BY work_id DESC LIMIT 2;
) AS t
Result:
+---------+
| working |
+---------+
| 1 | // not working
| 2 | // working
+---------+
This query will return 2 if user 1 is currently in the middle of a task, indicating that there is only one record for the most recent work_id. It will return 1 if the user has finished his previous task and has not yet received a new task, indicating two records (start and stop) for the most recent work_id.
I assume that the work_id which gets assigned is always increasing.
Like this:
select u.user_id, if(ifnull(w.is_completed, 0) = 1, 'Busy', 'Available') as Status
from users u
left join work w
on u.user_id = w.user_id
left join work w2
on w.user_id = w2.user_id and w.work_id < w2.work_id
where w2.work_id is null
Fiddle: http://sqlfiddle.com/#!9/03aa7/9
Query will return ALL users and their current availability as either 'Busy' or 'Available', depending on the status of their most recent work entry. Note this depends on the notion that work_id is an ascending, never repeating value, and that a work_id greater than another work_id, is guaranteed to be the more recent of the two.
If you want it to show the status for a specific user_id, just append AND user_id = ?? to the above query
select t.user_id,t.is_completed from( select * from
TableB
order by work_id desc )as t group by t.user_id
This will give latest work staus of a user
I have an invoices table which stores a history of invoices for every order, so one order can have multiple invoices.
However in everyday use I only want to select the newest invoice of every order.
An example of two invoices assigned to the same order:
invoice_id | order_id | invoice_number | created_at
=====================================================
1 | 42 | 10621 | 2014-05-28
2 | 42 | 10621 | 2014-05-31
I tryed the following
SELECT * FROM invoices GROUP BY order_id;
which groups the rows by the first row it finds, which is the oldest invoice. Adding an 'ORDER BY created_at DESC' clause doesn't change that.
Is there a way to get only the newest row for each order_id?
Use a self join on the maximum date of invoice,group by results are indeterminate they can't guarantee the order of results to be grouped below query should do the trick
SELECT
i.*
FROM
invoices i
JOIN
(SELECT
order_id,
MAX(created_at) created_at
FROM
invoices
GROUP BY order_id) ii
ON (
i.order_id = ii.order_id
AND i.created_at = ii.created_at
)
Here is a reasonable way to get the most recent row with your data. Note that it does not use group by:
select i.*
from invoices
where not exists (select 1
from invoices i2
where i2.order_id = i.order_id and i2.created_at > i.created_at
);
If performance is a concern, you will want an index on invoices(order_id, created_at).
This version changes the question from "Get me the invoice with the biggest date for each order" to "Get me the invoice for each order such that no other invoice for that order has a larger date".
I know I can do a count from mysql by doing this:
Select customer, Count (customer) Numbers from TblOrders group by customer
I want to count how many times each customer appears in the Order table.
After that I want to update Order table by swapping the customer id of the customer with the highest number of orders with another customer with id = 1.
Customer | Numbers
1 | 5
2 | 18
3 | 0
so here the highest was C2 so it'll swap C1 with C2 now after performing another count, I should get the table below.
Customer | Numbers
1 | 18
2 | 5
3 | 0
I also know the swapping can be done this way from a little research I've done.
Update TblOrders Set Customer = Case when 1 then 2
when 2 then 1
end
where TblOrders in (1, 2)
the problem with this statement is that it assumes I already know the two ID's that I'm swapping. but in case I don't know but I want the second one to be the ID with the highest number of orders...how do I go about it?
You want to issue an UPDATE request which affects all rows that belong to either one of the two customers in question. So the basic idea is this:
UPDATE TblOrders
SET customer = IF(customer == 'C1', #MaxCust, 'C1')
WHERE customer IN ('C1', #MaxCust)
If your customer IDs were integers, you could abbreviate this to
UPDATE TblOrders
SET customer = 1 + #MaxCust - customer
WHERE customer IN (1, #MaxCust)
This works because a + b - a = b and a + b - b = a, so a and b are exchanged.
My notation above was using a user variable #MaxCust to store the ID of the customer to be swapped. Depending on your environment, you might also use application code to enter the correct value into the query. Using a user variable, you could set it like this:
SELECT customer
FROM TblOrders GROUP BY customer
ORDER BY COUNT(*) DESC
LIMIT 1
INTO #MaxCust
after taking a look at # MvG's solutions, I came up with my own solution which is below.
SELECT customer FROM TblOrders GROUP BY customer ORDER BY COUNT(*) DESC LIMIT 1 INTO #MaxCust;
Update TblOrders Set Customer = Case
when 1 then #MaxCust
when #MaxCust then 1
end
where TblOrders in (1, #MaxCust );
I have two tables, simplified to the following:
users:
+-----+------+-----------+
| id | name | timestamp |
+-----+------+-----------+
vouchers:
+-----+------+
| id | code |
+-----+------+
I also have a third table, containing pairs of IDs:
recipients:
+-----+------+------+
| id | u_id | v_id |
+-----+------+------+
I need to periodically insert new pairs of IDs to the recipients table when a user's row is older than two weeks (the query will be scheduled to run once a day). IDs already present within the recipients table should not be retrieved.
I am currently unable to find an effective method of returning arbitrarily paired IDs from the two initial SELECT queries:
1. SELECT id FROM users WHERE date < NOW() - INTERVAL 2 WEEK AND id not in (select u_id from recipients)
2. SELECT id FROM vouchers WHERE id not in (select v_id from recipients) limit *by number of retrieved user IDs*
So far, all of my attempted JOINS have failed to achieve the desired result. I have established a solution using the two above queries, with a PHP for loop to pair the results before their insertion, but I am very aware that this is poor.
Thanks in advance,
You could create a Cartesian Product and remove the combinations already present in Recipients using a NOT EXISTS
Cartesian Product
INNER JOIN and , (comma) are semantically equivalent in the absence of
a join condition: both produce a Cartesian product between the
specified tables (that is, each and every row in the first table is
joined to each and every row in the second table).
SELECT *
FROM users u
, vouchers v
WHERE u.timestamp < NOW() -INTERVAL 2 WEEK
AND NOT EXISTS (
SELECT *
FROM Recipients r
WHERE r.u_id = u.id
AND r.v_id = v.id
)
I'm having trouble writing this Query. I have 2 tables, vote_table and click_table. in the vote_table I have two fields, id and date. the format of the date is "12/30/11 : 14:28:36". in the click_table i have two fields, id and date. the format of the date is "12.30.11".
The id's occur multiple times in both tables. What i want to do is produce a result that contains 3 fields: id, votes, clicks. the id column should have distinct id values, the votes column should have the total times that ID has the date 12/30/11% from the vote_table, and the clicks should have the total times that ID has the date 12.30.11 from the click table, so something like this:
ID | VOTES | CLICKS
001 | 24 | 50
002 | 30 | 45
Assuming that the types of the 'date' columns are actually either DATE or DATETIME (rather than, say, VARCHAR), then the required operation is fairly straight-forward:
SELECT v.id, v.votes, c.clicks
FROM (SELECT id, COUNT(*) AS votes
FROM vote_table AS v1
WHERE DATE(v1.`date`) = TIMESTAMP('2011-12-30')
GROUP BY v1.id) AS v
JOIN (SELECT id, COUNT(*) AS clicks
FROM click_table AS c1
WHERE DATE(c1.`date`) = TIMESTAMP('2011-12-30')
GROUP BY c1.id) AS c
ON v.id = c.id
ORDER BY v.id;
Note that this only shows ID values for which there is at least one vote and at least one click on the given day. If you need to see all the ID values which either voted or clicked or both, then you have to do more work.
If you have to normalize the dates because they are VARCHAR columns, the WHERE clauses become correspondingly more complex.