How to merge results of two mysql tables in one output - mysql

I have two similar mysql tables and want to get the data from both of them in one output (merge). How can I do it?
For this reason I have created two separate queries to check that I get what I'm looking for.
First: Table -> web_session
SELECT date_format(booking_time, '%m-%Y') AS m, count(booking_time) AS b
FROM web_session
WHERE
date(booking_time) >= date_sub(curdate(), interval 12 month)
AND
date(booking_time) <= date_add(curdate(), interval 6 month)
GROUP BY month(booking_time)
ORDER BY booking_time ASC;
Output:
m, b
10-2013, 15
11-2013, 6
12-2013, 13
01-2014, 10
02-2014, 10
03-2014, 25
04-2014, 1
Second: Table -> web_log
SELECT date_format(request_time, '%m-%Y') AS m, count(request_time) AS r
FROM web_log
WHERE
date(request_time) >= date_sub(curdate(), interval 12 month)
AND
date(request_time) <= date_add(curdate(), interval 6 month)
GROUP BY month(request_time)
ORDER BY request_time ASC;
Output:
m, r
03-2014, 45
04-2014, 35
desired output:
m, b, r
10-2013, 15, null
11-2013, 6, null
12-2013, 13, null
01-2014, 10, null
02-2014, 10, null
03-2014, 25, 45
04-2014, 1, 35

You need to join them. Try this:
SELECT T1.m,T1.b,T2.r FROM
(
SELECT date_format(booking_time, '%m-%Y') AS m, count(booking_time) AS b
FROM web_session
WHERE
date(booking_time) >= date_sub(curdate(), interval 12 month)
AND
date(booking_time) <= date_add(curdate(), interval 6 month)
GROUP BY month(booking_time)
ORDER BY booking_time ASC;) T1
LEFT OUTER JOIN
(SELECT date_format(request_time, '%m-%Y') AS m, count(request_time) AS r
FROM web_log
WHERE
date(request_time) >= date_sub(curdate(), interval 12 month)
AND
date(request_time) <= date_add(curdate(), interval 6 month)
GROUP BY month(request_time)
ORDER BY request_time ASC;) T2
ON T1.m=T2.m
ORDER BY T1.m
Output will be:
m b r
10-2013 15 null
11-2013 6 null
12-2013 13 null
01-2014 10 null
02-2014 10 null
03-2014 25 45
04-2014 1 35

Related

How to retrieve data from previous 4 weeks (mySQL)

I am trying to write a query to get the last 4 weeks (Mon-Sun) of data. I want every week of data to be stored with an individual and shared table.
every week data store based on name if same name repeated on single week amt should sum and if multiple name it should be show data individual, To see an example of what I am looking for, I have included the desired input and output below.
this is my table
date
amt
name
2022-04-29
5
a
2022-04-28
10
b
2022-04-25
11
a
2022-04-23
15
b
2022-04-21
20
b
2022-04-16
20
a
2022-04-11
10
a
2022-04-10
5
b
2022-04-05
5
b
i want output like this
date
sum(amt)
name
2022-04-25 to 2020-04-29
16
a
2022-04-25 to 2020-04-29
10
b
2022-04-18 to 2022-04-24
35
b
2022-04-11 to 2022-04-17
30
a
2022-04-04 to 2022-04-10
10
b
I would appreciate any pointers or 'best-practises' which I should employ to achieve this task.
You can try to use DATE_ADD with WEEKDAY get week first day and end day.
SELECT
CASE WHEN
weekofyear(`date`) = weekofyear(NOW())
THEN 'current week'
ELSE
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d'))
END 'date',
SUM(amt)
FROM T
GROUP BY
CASE WHEN
weekofyear(`date`) = weekofyear(NOW())
THEN 'current week'
ELSE
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d'))
END
sqlfiddle
EDIT
I saw you edit your question, you can just add name in group by
SELECT
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d')) 'date',
SUM(amt),
name
FROM T
GROUP BY
CONCAT(date_format(DATE_ADD(`date`, interval - WEEKDAY(`date`) day), '%Y-%m-%d'),' to ',date_format(DATE_ADD(DATE_ADD(`date`, interval -WEEKDAY(`date`) day), interval 6 day), '%Y-%m-%d')),
name
ORDER BY 1 desc
sqlfiddle
This is in SQL Server, and just a mess about. Hopefully it can be of some help.
with cteWeekStarts
as
(
select
n,dateadd(week,-n,DATEADD(week, DATEDIFF(week, -1, getdate()), -1)) as START_DATE
from
(values (1),(2),(3),(4)) as t(n)
), cteStartDatesAndEndDates
as
(
select *,dateadd(day,-1,lead(c.start_date) over (order by c.n desc)) as END_DATE
from cteWeekStarts as c
)
,cteSalesSumByDate
as
(
select s.SalesDate,sum(s.salesvalue) as sum_amt from
tblSales as s
group by s.SalesDate
)
select c3.n as WeekNum,c3.START_DATE,isnull(c3.END_DATE,
dateadd(day,6,c3.start_date)) as END_DATE,
(select sum(c2.sum_amt) from cteSalesSumByDate as c2 where c2.SalesDate
between c3.START_DATE and c3.END_DATE) as AMT
from cteStartDatesAndEndDates as c3
order by c3.n desc

Select date interval inside WHERE clause

I'm trying to query a list of loans that have been opened within the past 36 months. I'm also trying to query a count of loans that have been opened within the past 12 months as a separate column.
The query is returning the same values for both columns, how can I get get the count from both 36 month and 12 month intervals without running a separate query?
SELECT
`XDL-NAME`,
COUNT(distinct`XLN-LOANDATE`) as '36 Month Count',
COUNT(IF(`XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 12 MONTH), 1 , NULL)) AS '12 Month Count'
from
LOAN
JOIN
DEALER ON `XLN-DLNO` = `XDL-NUM` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 36 MONTH)
GROUP BY `XDL-NAME`
Instead of count for 12 months, change to sum like below
SELECT
`XDL-NAME`,
COUNT(distinct`XLN-LOANDATE`) as '36 Month Count',
SUM(IF(`XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 12 MONTH), 1 , 0)) AS '12 Month Count'
from
LOAN
JOIN
DEALER ON `XLN-DLNO` = `XDL-NUM` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 36 MONTH)
GROUP BY `XDL-NAME`
Try this:
SELECT
`XDL-NAME`,
count((SELECT `XLN-LOANDATE` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 36 MONTH))) AS '36 Month Count',
count((SELECT `XLN-LOANDATE` WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(),INTERVAL 12 MONTH))) AS '12 Month Count',
from
LOAN
JOIN
DEALER ON `XLN-DLNO` = `XDL-NUM`
GROUP BY `XDL-NAME`
What I did was use subqueries to count each interval you wanted. This way they should output with Name, 36 month count, 12 month count all on one line (record).
I would expect this query to return the two separate counts:
SELECT `XDL-NAME`,
COUNT(*) as `36 Month Count`,
SUM(`XLN-LOANDATE` >= DATE_SUB(NOW(), INTERVAL 12 MONTH)) AS `12 Month Count`
FROM loan l join
dealer d
ON `XLN-DLNO` = `XDL-NUM`
WHERE `XLN-LOANDATE` >= DATE_SUB(NOW(), INTERVAL 36 MONTH)
GROUP BY `XDL-NAME`;
Try SUM like:
SUM(IF('2016-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0)) AS '12 Month Count'
Sample
mysql> SELECT IF('2016-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0);
+----------------------------------------------------+
| IF('2016-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0) |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT IF('2015-12-22' >= NOW() -INTERVAL 12 MONTH, 1, 0);
+----------------------------------------------------+
| IF('2015-12-22' >= NOW() -INTERVAL 12 MONTH, 1, 0) |
+----------------------------------------------------+
| 1 |
+----------------------------------------------------+
1 row in set (0,00 sec)
mysql> SELECT IF('2015-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0);
+----------------------------------------------------+
| IF('2015-12-21' >= NOW() -INTERVAL 12 MONTH, 1, 0) |
+----------------------------------------------------+
| 0 |
+----------------------------------------------------+
1 row in set (0,00 sec)
mysql>

my sql query for last 7 days data?if data not there then even fetch date and shows with 0 or null

i have made one demo Enity in sql Fidldle.
my table have following collumn
displayId | displaytime | campaignId
now what i want is to select the last 7 days entry for the particular campaignId (i mean where campaignId="")
there should be multiple entry for the same date with same campaign id..so i want to show sum of total campaignId with their date
so if there is 7 records for date 2013-3-8 and other date then it shows me record like
2013-03-02 | 1
2013-03-03 | 1
2013-03-04 | 0
2013-03-05 | 0
2013-03-06 | 0
2013-03-07 | 2
2013-03-08 | 7
in following query its just shows the date with their count which have more then 0 count...
e.g.
what i have tried is as follows..but it just give me one record which have entry in database...
2013-03-08 | 7
SELECT date(a.displayTime) AS `DisplayTime`,
ifnull(l.TCount,0) AS TCount
FROM a_ad_display AS a
INNER JOIN
(SELECT count(campaignId) AS TCount,
displayTime
FROM a_ad_display
WHERE CONVERT_TZ(displaytime,'+00:00','-11:00') >= DATE_SUB(CONVERT_TZ(CURDATE(),'+00:00','-11:00') ,INTERVAL 1 DAY)
AND CONVERT_TZ(displaytime,'+00:00','-11:00') <= CONVERT_TZ(CURDATE(),'+00:00','-11:00')
AND campaignId = 20747
GROUP BY DATE(displayTime)) AS l ON date(a.displayTime) = date(l.displayTime)
GROUP BY DATE(a.displayTime)
ORDER BY a.displaytime DESC LIMIT 7
i have implemented time zone in my query so if u can help me with the simple query then its ok..dont include Convert_Tz line.
this is http://sqlfiddle.com/#!2/96600c/1 link of my dummy entitiy
If you use a dates table, your query can be as simple as:
select dates.fulldate, count(a_ad_display.id)
from dates
left outer join a_ad_display ON dates.fulldate = a_ad_display.displaytime
[AND <other conditions here>]
where dates.fulldate BETWEEN date_add(curdate(), interval -6 day) AND curdate()
group by dates.fulldate
http://sqlfiddle.com/#!2/51e17/3
Without using a dates table, here's one way. It's ugly and probably terrible for performance:
select displaytime, sum(c)
from
(
select displaytime, count(a_ad_display.id) AS c
from a_ad_display
where displaytime BETWEEN date_add(curdate(), interval -6 day) AND curdate()
group by displaytime
union all
select curdate(), 0
union all
select date_add(curdate(), interval -1 day), 0
union all
select date_add(curdate(), interval -2 day), 0
union all
select date_add(curdate(), interval -3 day), 0
union all
select date_add(curdate(), interval -4 day), 0
union all
select date_add(curdate(), interval -5 day), 0
union all
select date_add(curdate(), interval -6 day), 0
) x
group by displaytime
order by displaytime
http://sqlfiddle.com/#!2/96600c/16
Simple!You can done by PHP. First create date array like
date = date('Y-m-d'); $date1 = date('Y-m-d', strtotime('-1 days')); $date2 = date('Y-m-d', strtotime('-2 days'));$date3 = date('Y-m-d', strtotime('-3 days'));$date4 = date('Y-m-d', strtotime('-4 days'));$date5 = date('Y-m-d', strtotime('-5 days'));$date6 = date('Y-m-d', strtotime('-6 days'));
$dt_arr = array($date6,$date5,$date4,$date3,$date2,$date1,$date);
for last 7 days from today then use foreach and run query with where date field inside foreach like
foreach ($dt_arr as $value)
{
$qry = mysqli_fetch_array(mysqli_query($link,"select * from table where dt_field = $value"));
if($qry['value'] == '')
{
$valfield = 0;
$dtfiled = $value;
}

Date calculation ranking - Assign a value for event age

I'm trying to assign a value for events based on it's age using this:
SELECT u.iduser, timeIsImportant
FROM user AS u
LEFT OUTER JOIN(
SELECT action, user_id, action_time,
(IF(bb.action_time < DATE_SUB(CURDATE(), INTERVAL 7 DAY),
(CASE
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 3 MONTH) AND CURDATE() THEN 0.1
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 6 MONTH) AND CURDATE() THEN 0.2
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 12 MONTH) AND CURDATE() THEN 0.4
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 18 MONTH) AND CURDATE() THEN 0.7
WHEN bb.action_time BETWEEN DATE_SUB(CURDATE(), INTERVAL 24 MONTH) AND CURDATE() THEN 1.0
END), 0))
AS timeIsImportant
FROM bigbrother AS bb
ORDER BY bigbrother.uid DESC LIMIT 1)
AS bbb
ON
bbb.user_id = u.iduser AND bbb.action = "C"
WHERE u.iduser = 2;
The idea is that older 'events' on the bigbrother table need to subtract different values from a ranking query calculation. The timeIsImportant value from the query above, would be the agePoints on the following example.
sample data:
row1 row2
------------- -------------
rank: 4.7 rank 4.9
agePoints: 0.1 agePoints 0.4
timedRank: (rank-AgePoints) timedRank: (rank-AgePoints)
-------------------------------------------------------------
SQL: ORDER BY timedRank DESC
row1, row2
SQL: ORDER BY timedRank ASC
row2, row1
I wonder if there's another way to assign the values based on events age, since I'm doing this calculation on every page load in order to rank search results and found that this piece of code slows the overall performance when nested within the search query.

SQL NOT IN Query

Can anyone help me with this MySQL query?
SELECT p.ProductID,
p.StoreID,
p.DiscountPercentage
FROM Products p
WHERE p.IsSpecial = 1
AND p.SpecialDate >= date_sub(now(),interval 15 minute)
AND p.DiscountPercentage >= ?DiscountPercentage
AND p.ProductID NOT IN (SELECT lf.LiveFeedID
From LiveFeed lf
WHERE p.ProductID = lf.ProductID
AND lf.DateAdded >= date_sub(now(),interval 30 day))
AND p.StoreID NOT IN (SELECT lf.LiveFeedID
From LiveFeed lf
WHERE p.StoreID = lf.StoreID
AND lf.DateAdded >= date_sub(now(),interval 6 hour))
ORDER BY p.StoreID, p.DiscountPercentage DESC
I'm trying join where the ProductID is not in the livefeed table in the last 30 days and where the storeid is not in the livefeed table in the last 6 hours, but it does not seem to be working. Any idea what I'm doing wrong?
At a glance, it would appear that your first subquery should be selecting ProductID, not LiveFeedID and your second subquery should be selecting StoreID not LiveFeedID
I'm too late:
SELECT p.ProductID,
p.StoreID,
p.DiscountPercentage
FROM Products p
WHERE p.IsSpecial = 1
AND p.SpecialDate >= date_sub(now(),interval 15 minute)
AND p.DiscountPercentage >= ?DiscountPercentage
AND p.ProductID NOT IN (SELECT lf.productid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 30 DAY))
AND p.storeid NOT IN (SELECT lf.storeid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 6 HOUR))
ORDER BY p.StoreID, p.DiscountPercentage DESC
You were using EXISTS syntax with a correllated subquery...
I'm trying to get the top discount for each store.
In that case, use:
SELECT p.StoreID,
MAX(p.DiscountPercentage)
FROM Products p
WHERE p.IsSpecial = 1
AND p.SpecialDate >= date_sub(now(),interval 15 minute)
AND p.DiscountPercentage >= ?DiscountPercentage
AND p.ProductID NOT IN (SELECT lf.productid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 30 DAY))
AND p.storeid NOT IN (SELECT lf.storeid
FROM LIVEFEED lf
WHERE lf.DateAdded >= DATE_SUB(NOW(), INTERVAL 6 HOUR))
GROUP BY p.storeid
ORDER BY p.StoreID, p.DiscountPercentage DESC