I want to join 2 tables:
source_table
----------------------------------
| source_id label |
|----------------------------------|
| 1 Contact Form |
| 2 E-Mail |
| 3 Inbound Call |
| 4 Referral |
----------------------------------
related_table
---------------------------------------
| id created_at source |
|---------------------------------------|
| 1 2013-12-26 2 |
| 2 2013-12-26 2 |
| 3 2013-12-26 4 |
| 4 2013-12-25 1 |
| 5 2013-12-18 2 |
| 6 2013-12-16 4 |
| 7 2013-11-30 2 |
---------------------------------------
So that it looks like this:
---------------------------------------
| created_at source amount |
|---------------------------------------|
| 2013-12-26 E-Mail 2 |
| 2013-12-26 Referral 1 |
| 2013-12-25 Contact Form 1 |
| 2013-12-18 E-Mail 1 |
| 2013-12-16 Referral 1 |
---------------------------------------
I want to count the occurrences of each source in related_table grouped by the source for each date in the range.
But I'm not sure how to write the query.
Here's what I have so far:
SELECT DISTINCT
source_table.source_id,
source_table.label AS source,
related_table.created_at,
COUNT(*) AS amount
FROM source_table
INNER JOIN related_table
ON related_table.source=source_table.source_id AND
related_table.created_at>='2013-12-01' AND
related_table.created_at<='2013-12-31'
GROUP BY `source`
ORDER BY `created_at` ASC
I'm not very good with SQL, so the above query might be far off from what I need to have. All I know is that it doesn't work as expected.
My implementation:
select created_at, s.label, amount
from
(
select count(r.Source) as amount, r.source, r.created_at
from related_table r
group by r.source, r.created_at) a inner join source_table s
on a.source = s.source_id
where created_at between '2013-12-01' and '2013-12-31'
order by amount desc, created_at desc
http://sqlfiddle.com/#!2/841bd/2
adjusted demo to your example...
SELECT
created_at
,label as source
,COUNT(*) AS amount
FROM source_table
INNER JOIN related_table
ON source_table.source_id = related_table.source
GROUP BY label, created_at
ORDER BY created_at DESC
Related
i have 2 tables(say customer and details) containing following data. I need to print the details of the people who have invested maximum amount.
Customer:
+------+------------+--------+
| name | visited | amount |
+------+------------+--------+
| xyz | 2018-04-11 | 100 |
| xyz | 2018-04-11 | 1000 |
| abc | 2018-02-21 | 500 |
| xyz | 2018-03-11 | 700 |
| abc | 2018-01-24 | 50 |
+------+------------+--------+
Details:
+------+------------+
| name | detail |
+------+------------+
| abc | california |
| xyz | hongkong |
+------+------------+
I have found the customer who have invested the maximum amount using the query
select name,sum(amount)
from (
select name,amount
from customer
where visited >= DATE_SUB(CURDATE(),INTERVAL 8 MONTH)
) as subtable
group by name
order by amount
limit 1;
i have the following output
+------+-------------+
| name | sum(amount) |
+------+-------------+
| xyz | 1800 |
+------+-------------+
now how do i find the details of xyz from details table? I need to do this all in a single query. My output must be like.
+------+------------+
| name | detail |
+------+------------+
| xyz | hongkong |
+------+------------+
My stuck, how to proceed this?
select d.name, d.details, sum(c.amount)
from details d
join customer c on c.name = d.name
where c.visited >= DATE_SUB(CURDATE(),INTERVAL 8 MONTH)
group by d.name
order by sum(c.amount) desc
limit 1
You need to JOIN to details table. I've decided to use subquery to limit the amount of rows being looked up for the join operation.
select c.name, d.detail
from (
select
name,
sum(amount) as sum_amount
from customer
where visited >= DATE_SUB(CURDATE(),INTERVAL 8 MONTH)
group by name
order by sum_amount
limit 1
) c
left join details d on c.name = d.name
Note that I've removed your subquery as it was superfluous.
To get the following outputs you can write query with join like below :
Output:-
+------+------------+
| name | detail |
+------+------------+
| xyz | hongkong |
+------+------------+
Query:-
select d.name, d.details
from details d
join customer cust on cust.name = d.name and
cust.visited >= DATE_SUB(CURDATE(),INTERVAL 8 MONTH)
group by d.name
order by sum(cust.amount) desc
limit 1;
If you want to print sum Amount along with that then you have to just add one more column in your select statement :
Output:-
+------+------------+--------------+
| name | detail | sum(amount) |
+------+------------+--------------+
| xyz | hongkong | 1800 |
+------+------------+--------------+
Query:-
select d.name, d.details, sum(cust.amount)
from details d
join customer cust on cust.name = d.name and
cust.visited >= DATE_SUB(CURDATE(),INTERVAL 8 MONTH)
group by d.name
order by sum(cust.amount) desc
limit 1;
How do I find the oldest date from the most recent set of records in MySQL?
Consider the below
+--------+-----------+------------+
| ID | PRODUCTID | DATEACTIVE |
+--------+-----------+------------+
| 546502 | 23405 | 2017-07-20 |
| 545075 | 23405 | 2017-07-19 |
| 543651 | 23405 | 2017-07-18 |
| 456783 | 23405 | 2017-01-04 |
| 456782 | 23405 | 2017-01-03 |
| 456781 | 23405 | 2017-01-02 |
| 456780 | 23405 | 2017-01-01 |
| 65453 | 23405 | 2016-07-19 |
| 65452 | 23405 | 2016-07-18 |
+--------+-----------+------------+
I want to be able to find the most recent time a product was activated (18th July 2017)
Pls next time follow what Sloan said in the comments.
If I understood your question, you could use something like this.
The query, in the inner part, "groups" the consecutive dates, giving a consecutive number for each "group".
Then select only the "first" group (the more recent) and numbers the rows in ascending order by date.
Finally, the row with the first "row number" is selected.
SELECT *
FROM (
SELECT #rn:=#rn+1 AS RN,
A.*
FROM (
SELECT #gr:= IF(#prev_date=DATE_ADD(dateactive, INTERVAL +1 DAY), #gr, #gr+1) AS GR
,TN.*
,#prev_date:=dateactive AS PD
FROM TN
CROSS JOIN (SELECT #gr:=0, #prev_date:=(SELECT MAX(dateactive) FROM TN)) R
ORDER BY DATEACTIVE DESC
) A
CROSS JOIN (SELECT #rn:=0) R2
WHERE GR=1
ORDER BY DATEACTIVE
)B
WHERE RN=1;
Output:
RN GR id productid dateactive PD
1 1 543651 23405 18.07.2017 00:00:00 2017-07-18
SELECT MAX(DATEACTIVE) as most_recent_time
FROM `YOUR_TABLE_NAME`
WHERE PRODUCTID = 'YOUR_ID'
You could use ORDER BY to sort the data by date, See code below:
SELECT *
FROM `YOUR_TABLE_NAME`
WHERE `PRODUCTID` = 'YOUR_ID'
ORDER BY `DATEACTIVE` DESC;
Have Users table, where users can have multiple accounts.
Table can look like this:
u_id | u_parent_d | date_added
1 | 1 | 2017-01-01
2 | 2 | 2017-01-04
3 | 1 | 2017-01-05
4 | 4 | 2017-01-06
5 | 2 | 2017-01-07
How can I order these records by date added but grouped connected accounts together
u_id | u_parent_d | date_added
5 | 2 | 2017-01-07
2 | 2 | 2017-01-04
4 | 4 | 2017-01-06
3 | 1 | 2017-01-05
1 | 1 | 2017-01-01
You can build your query in two steps. First of all get the maximum date for each u_parent_d
select u_parent_d, max(date_added) as max_date
from Users
group by u_parent_d
Then you can join this with the initial table, and use max_date for sorting
select t1.*
from Users t1
join (
select u_parent_d, max(date_added) as max_date
from Users
group by u_parent_d
) t2
on t1.u_parent_d = t2.u_parent_d
order by t2.max_date desc, t1.date_added desc
Order both by date and parent id:
SELECT * FROM users
ORDER BY u_parent_id, date_added DESC
I have two tables, one that store product information and one that stores reviews for the products.
I am now trying to get the number of reviews submitted for the products between two dates but for some reason I get the same results regardless of the dates i put.
This is my query:
SELECT
productName,
COUNT(*) as `count`,
avg(rating) as `rating`
FROM `Reviews`
LEFT JOIN `Products` using(`productID`)
WHERE `date` BETWEEN '2015-07-20' AND '2015-07-30'
GROUP BY
`productName`
ORDER BY `count` DESC, `rating` DESC;
This returns:
+------------+---------------------+
| productName| count|rating |
+------------+------+--------------+
| productA | 23 | 4.3333333 |
| productB | 17 | 4.25 |
| productC | 10 | 3.5 |
+------------+---------------------+
Products table:
+---------+-------------+
|productID | productName|
+---------+-------------+
| 1 | productA |
| 2 | productB |
| 3 | productC |
+---------+-------------+
Reviews table
+---------+-----------+--------+---------------------+
|reviewID | productID | rating | date |
+---------+-----------+--------+---------------------+
| 1 | 1 | 4.5 | 2015-07-27 17:47:01|
| 2 | 1 | 3.5 | 2015-07-27 18:54:22|
| 3 | 3 | 2 | 2015-07-28 13:28:37|
| 4 | 1 | 5 | 2015-07-28 18:33:14|
| 5 | 2 | 1.5 | 2015-07-29 11:58:17|
| 6 | 2 | 3.5 | 2015-07-30 15:04:25|
| 7 | 2 | 2.5 | 2015-07-30 18:11:11|
| 8 | 1 | 3 | 2015-07-30 18:26:23|
| 9 | 1 | 3 | 2015-07-30 21:35:05|
| 10 | 1 | 4.5 | 2015-07-31 14:25:47|
| 11 | 3 | 0.5 | 2015-07-31 14:47:48|
+---------+-----------+--------+---------------------+
when I put two random dates that I do know for sure they not on the date column, I will still get the same results. Even when I want to retrieve records only on a certain day, I get the same results.
You should not use left join, because by doing so you retrieve all the data from one table. What you should use is something like :
select
productName,
count(*) as `count`,
avg(rating) as `rating`
from
products p,
reviews r
where
p.productID = r.productID
and `date` between '2015-07-20' and '2015-07-30'
group by productName
order by count desc, rating desc;
If the result, given your sample data, that you're looking for is:
| productName | count | rating |
|-------------|-------|--------|
| productA | 5 | 4 |
| productB | 3 | 3 |
| productC | 1 | 2 |
This is the count and average of reviews made on any date between 2015-07-20 and 2015-07-30 inclusive.
Then the there are two issues with your query. First, you need to change the join to a inner join instead of a left join, but more importantly you need to change the date condition as you are currently excluding reviews that fall on the last date on the range, but after midnight.
This happens because your between clause compares datetime values with date values so the comparison ends up being date between '2015-07-20 00:00:00' and '2015-07-30 00:00:00' which clearly excludes some dates at the end.
The fix is to either change the date condition so that the end is a day later:
where date >= '2015-07-20' and date < '2015-07-31'
or cast the date column to a date value, which will remove the time part:
where date(date) between '2015-07-20' and '2015-07-30'
Sample SQL Fiddle
You are using a LEFT JOIN between your reviews and your products tables. This will result in all the rows of reviews being shown with some rows having all product columns left empty.
You should use INNER JOIN, as this will filter only the wanted results.
(In the end I can only guess, since I don't even know which column belongs to which table ...)
The full query (very similar to Angelo Giannis's solution):
select
productName,
count(*) as `count`,
avg(rating) as `rating`
from
products INNER JOIN reviews USING(productId)
where date between '2015-07-20' and '2015-07-30'
group by productName
order by count desc, rating desc;
Here a fiddle with my and Angelo's solution (they both work).
Help please, I have a table like this:
| ID | userId | amount | type |
-------------------------------------
| 1 | 10 | 10 | expense |
| 2 | 10 | 22 | income |
| 3 | 3 | 25 | expense |
| 4 | 3 | 40 | expense |
| 5 | 3 | 63 | income |
I'm looking for a way to use one query and retrive the balance of each user.
The hard part comes when the amounts has to be added on expenses and substracted on incomes.
This would be the result table:
| userId | balance |
--------------------
| 10 | 12 |
| 3 | -2 |
You need to get each totals of income and expense using subquery then later on join them so you can subtract expense from income
SELECT a.UserID,
(b.totalIncome - a.totalExpense) `balance`
FROM
(
SELECT userID, SUM(amount) totalExpense
FROM myTable
WHERE type = 'expense'
GROUP BY userID
) a INNER JOIN
(
SELECT userID, SUM(amount) totalIncome
FROM myTable
WHERE type = 'income'
GROUP BY userID
) b on a.userID = b.userid
SQLFiddle Demo
This is easiest to do with a single group by:
select user_id,
sum(case when type = 'income' then amount else - amount end) as balance
from t
group by user_id
You could have 2 sub-queries, each grouped by id: one sums the incomes, the other the expenses. Then you could join these together, so that each row had an id, the sum of the expenses and the sum of the income(s), from which you can easily compute the balance.