get monthwise row count from datewise data in mysql - php

I have two tables:
table 1.a
id--entry_date-amount
============================
2---2016-04-14--$400
3---2016-04-14--$400
4----2017-07-14--$200
5---2017-07-14--$500
6---2017-05-14--$600
7----2017-06-18--$100
table 2.b
id--entry_date
===========================
2---2016-04-14--$230
3---2016-04-14--$230
4----2017-07-14--$567
5---2017-07-14--$600
6---2017-05-14--$560
7----2017-06-18--$90
8---2016-04-14--$100
from the two tables how can i get count with montwise
my desired result:
month_name--total(count form table a)--total(count form table b)--amount(table a)--amount(table b)
========================================================
April,16-----------2-------------------3---$800-$500
May,17-----------1-------------------1 --$600--$700
June,17-----------2-------------------2--$100--$800
July,17-----------2-------------------2---$700-$400
this is the demo data.
I want to show data from two tables in a single query month wise.
How can i do this?
I tried:
SELECT MONTHNAME(r.entry_date),r.a_total FROM(
SELECT
IFNULL((SELECT COUNT(tr.id) AS amount FROM a AS tr WHERE MONTH(tr.entry_date)=MONTH(t.entry_date)),0) AS a_total
,t.entry_date
FROM(SELECT tr.id,tr.entry_date
FROM a AS tr
WHERE DATE(tr.entry_date) BETWEEN '2017-07-01' AND '2018-06-30') t
GROUP BY MONTH(t.entry_date)) r
But takes 58 seconds for simple query. How can i make this in a simple query?

You can get the counts and sum from each table individually, then use UNION to combine the two result sets into one result set. Something like this :
SELECT Month_name,
SUM(aCount) AS aCount,
SUM(bCount) AS bCount,
SUM(aAmount) AS aAmount,
SUM(bAmount) AS bAmount
FROM
(
SELECT
MONTHNAME(a.entry_date) AS Month_name,
COUNT(a.id) AS aCount,
0 AS bCount,
SUM(a.amount) AS aAmount,
0 AS bAmount
FROM a
GROUP BY MONTHNAME(a.entry_date)
UNION ALL
SELECT
MONTHNAME(b.entry_date) AS Month_name,
0 AS aCount,
COUNT(b.id) AS bCount,
0 AS aAmount,
SUM(b.amount) AS bAmount
FROM b
GROUP BY MONTHNAME(b.entry_date)
) AS t
GROUP BY Month_Name;
live demo

user9131497 has a good design for the big picture. However, I would suggest stuff like this for handling the dates:
SELECT DATE_FORMAT(entry_date, "%M,%y") AS 'Month',
COUNT(*) AS 'aCount'
FROM a
GROUP BY LEFT(entry_date, 7) -- eg, "2017-03"
Try that to see what I mean.
Note that this will work beyond a year. Or did you need January values from all years to be combined?? -- That's what your solution and user9131497's will do. Mine keeps them separate.

Related

SUM 2 values in mysql to make leaderboard

I want make a leaderboard from my database, I already make a code but the sql says error
"SET #a1 = (SELECT SUM(d.poin_diskusi)
FROM diskusi d
GROUP BY d.id_akun)
MySQL said: Documentation
#1242 - Subquery returns more than 1 row"
heres my sql query :
SET #a1 = (SELECT SUM(d.poin_diskusi)
FROM diskusi d
GROUP BY d.id_akun);
SET #a2 = (SELECT SUM(j.nilai_jawaban)
FROM jawaban j
GROUP BY j.id_akun);
SET #hasil = #a1 + #a2;
SELECT #hasil
Thank you !
this is an example data in table jawaban:
this is an example data in table diskusi:
and my desired answer:
where tera123 have 135 TOTAL(d.poin_diskusi+j.nilai_jawaban) and david123 have 90 TOTAL(d.poin_diskusi+j.nilai_jawaban)
the point is to show TOTAL for every user
It looks to me (without looking at your images; if you want to show information, please provide it in text) like you want something like:
select id_akun, sum(point_value) as total_points from (
select id_akun, sum(poin_diskusi) as point_value
from diskusi group by id_akun
union all
select id_akun, sum(nilai_jawaban) as point_value
from jawaban group by id_akun
) as point_values
group by id_akun
The problem are the GROUP BY keywords. Inside the images you provided with example data, one can see that there are multiple entries for the columns jawaban.id_akun and diskusi.id_akun. Because of that, both SELECT will return multiple rows as result, for each different value of the id columns one summed up row. Try it without the GROUP BY clause.

Sum of 2 different non matching columns from 2 different tables

This s my first question on SO, so please bear if I am not super clear! I am trying to sum up values of 2 columns from 2 tables. Both table values have a common ID called 'imid'. These imids are further divided as 'pmid' (say 1 imid can have one or multiple pmids). Both tables have different structures. I would want to sum values on 1 column from table1 and another column from table(to use it for a php calculation). When I try JOIN it always gives me a timeout error. Query below.
SELECT F.`imid` AS imid, SUM( F.Impression ) AS si, D.accmgr AS accmgr, D.cmname AS cmname,sum(D.Item_Impression_Cap) AS sim
FROM trasactions F, rawdata D
WHERE F.`imid` = D.`imid`
AND F.EntryDate LIKE '2017-%-%'
GROUP BY D.`imid`, F.`imid` ORDER BY F.`imid` ASC
I get results, but not even close to the correct numbers.(eg) Impression as 6,557,824 instead of 1,233,287 for a particular imid.
Not sure where I am wrong! Any help would be great...
Edit: Thanks for the responses...I managed to write the query...
SELECT F.`imid`, F.si , F.imname,D.Item_Start_Date ,D.sim, D.Item_End_Date, D.accmgr, D.cmname
FROM (SELECT `imid` AS imid, SUM(Impression ) AS si, adname AS imname, EntryDate FROM trasactions GROUP BY imid) F LEFT JOIN
(SELECT imid,Item_Start_Date, Item_End_Date, accmgr AS accmgr, cmname AS cmname, sum(Item_Impression_Cap) AS sim FROM rawdata GROUP BY imid) D ON F.`imid`=D.`imid`
WHERE D.cmname IS NOT NULL
GROUP BY F.`imid`
ORDER BY F.`imid` ASC
Now there is a new question! I am doing some calculations based on the array values derived from the query above...(eg) $pacing = $row['si']/$avgday*100;
Say I am listing the 'Pacing' for all items active. Would it be possible to count values from variables. (eg) Would want to show the count of items where $pacing is less than 100%. Would it even be possible to do that!! Thanks again.

SQL Left Join Return Latest Row

Two tables, with a left join. For ease table 1 and table 2.
Table 1 contains a list of people and their current status, table 2 is all of their "invites". All im trying to do as part of the join is show in a list all the current "people" and then the LATEST invite status (from table 2) so return a single row from table 2.
I have everything working... but its duplicating for example if a person has had multiple invites it will put them twice on the list. I just want to limit it to
$sql = "SELECT table1.fieldname as table1fielname table2.fieldname [more fields]
FROM xxx
LEFT JOIN xxx on table1.sharedid=table2.sharedid
WHERE XXX LIMIT 1 ";`
Obvioulsy the limit 1 doesnt do what its supposed to. I have tried adding additional select statements in brackets but being honest it just breaks everything and im not an expert at all.
I'm not an expert too but I'll try. Have you tried to use DISTINCT?
For exemple:
SELECT DISTINCT column_name1,column_name2
FROM table_name; [...]
It normally delete double matches.
Here are the links:
http://www.w3schools.com/sql/sql_distinct.asp
https://www.techonthenet.com/oracle/distinct.php
Give example data. And use good table and column names. For example:
(this returns all rows that satisfy the join):
WITH people(ppl_id,ppl_name,status) AS (
SELECT 1,'Arthur','active'
UNION ALL SELECT 2,'Tricia','active'
), invites(ppl_id,inv_id,inv_date) AS (
SELECT 1,1, DATE '2017-01-01'
UNION ALL SELECT 1,2, DATE '2017-01-07'
UNION ALL SELECT 1,3, DATE '2017-01-08'
UNION ALL SELECT 2,1, DATE '2017-01-01'
UNION ALL SELECT 2,2, DATE '2017-01-08'
)
SELECT
*
FROM people
JOIN invites USING(ppl_id)
ORDER BY 1
;
ppl_id|ppl_name|status|inv_id|inv_date
1|Arthur |active| 1|2017-01-01
1|Arthur |active| 3|2017-01-08
1|Arthur |active| 2|2017-01-07
2|Tricia |active| 2|2017-01-08
2|Tricia |active| 1|2017-01-01
But we want only 'Arthur' with '2017-01-08' and 'Tricia' with '2017-01-08'.
With any database that supports ANSI 99, you could try with a temporary table containing the newest invitation date per "people id", and join that temporary table with the invitations table. We call that table newest_invite_date, and, apparently, it does what we expect it to do:
WITH people(ppl_id,ppl_name,status) AS (
SELECT 1,'Arthur','active'
UNION ALL SELECT 2,'Tricia','active'
), invites(ppl_id,inv_id,inv_date) AS (
SELECT 1,1, DATE '2017-01-01'
UNION ALL SELECT 1,2, DATE '2017-01-07'
UNION ALL SELECT 1,3, DATE '2017-01-08'
UNION ALL SELECT 2,1, DATE '2017-01-01'
UNION ALL SELECT 2,2, DATE '2017-01-08'
), newest_invite_date(ppl_id,inv_date) AS (
SELECT ppl_id,MAX(inv_date)
FROM invites
GROUP BY ppl_id
)
SELECT
people.ppl_id
, people.ppl_name
, people.status
, newest_invite_date.inv_date
FROM people
JOIN newest_invite_date USING(ppl_id)
ORDER BY 1
;
ppl_id|ppl_name|status|inv_date
1|Arthur |active|2017-01-08
2|Tricia |active|2017-01-08
Is this what you were looking for?
Happy playing ...
Marco the Sane

How to calculate difference between values coming from the same row in mysql

I am trying to calculate the difference of values list coming from a database.
I would like to achieve it using php or mysql, but I do not know how to proceed.
I have a table named player_scores. One of its rows contains the goals scored.
Ex.
pl_date pl_scores
03/11/2014 18
02/11/2014 15
01/11/2014 10
I would like to echo the difference between the goals scored during the matches played in different dates.
Ex:
pl_date pl_scores diff
03/11/2014 18 +3
02/11/2014 15 +5
01/11/2014 10 no diff
How can I obtain the desired result?
You seem to want to compare a score against the score on a previous row.
Possibly simplest if done using a a sub query that gets the max pl_date that is less than the pl_date for the current row, then joining the results of that sub query back against the player_scores table to get the details for each date:-
SELECT ps1.pl_date, ps1.pl_scores, IF(ps2.pl_date IS NULL OR ps1.pl_scores = ps1.pl_scores, 'no diff', ps1.pl_scores - ps1.pl_scores) AS diff
FROM
(
SELECT ps1.pl_date, MAX(ps2.pl_date) prev_date
FROM player_scores ps1
LEFT OUTER JOIN player_scores ps2
ON ps1.pl_date > ps2.pl_date
GROUP BY ps1.pl_date
) sub0
INNER JOIN player_scores ps1
ON sub0.pl_date = ps1.pl_date
LEFT OUTER JOIN player_scores ps2
ON sub0.prev_date = ps2.pl_date
There are potentially other ways to do this (for example, using variables to work through the results of an ordered sub query, comparing each row with the value stored in the variable for the previous row)
SELECT score FROM TABLE WHERE DATE = TheDateYouWant
$score = $data['score'];
SELECT score FROM TABLE WHERE date = dateYouWant
$difference = $score - $data['score'];
Something like this?
You could use two queries, one to get the value to use in the comparison (in the example below is the smaller number of scores) and the second one to get the records with a dedicated column with the difference:
SELECT MIN(pl_scores);
SELECT pl_date, pl_scores, (pl_scores - minScore) as diff FROM player_scores;
Or, using a transaction (one query execution php side):
START TRANSACTION;
SELECT MIN(Importo) FROM Transazione INTO #min;
SELECT Importo, (Importo - #min) as diff FROM Transazione;
select *,
coalesce(
(SELECT concat(IF(t1.pl_scores>t2.pl_scores,'+',''),(t1.pl_scores-t2.pl_scores))
FROM tableX t2 WHERE t2.pl_date<t1.pl_date ORDER BY t2.pl_date DESC LIMIT 1)
, 'no data' ) as diff
FROM tableX t1
WHERE 1
order by t1.pl_date DESC

MySQL query that checks in another table

I've got a problem with two mysql tables. I've done some code and I think I am close to the solution, but I'm not sure if this is right.
So here are the two tables:
Table 1: Blogs
Columns: ID, agp_name, agp_url, agp_username, agp_password
Table 2: Keywords
Columns: ID, agp_user_id, agp_order_id, agp_blog_id, agp_keywords, agp_keywords_date
What I want is to get one random row from Table1 based on the following condition: if the agp_keyword match one of the keywords in the last 5 days then do not include into the result.
So far I did this:
SELECT
t1.agp_user_id, t1.agp_order_id, t1.agp_blog_id, t1.agp_keywords, t1.agp_keywords_date, t2.agp_name, t2.agp_url, t2.agp_username, t2.agp_password
FROM table1 AS t1
INNER JOIN (
SELECT ID, agp_name, agp_url, agp_username, agp_password, agp_blogposts
FROM table2
) AS t2 ON t1.agp_blog_id = t2.ID
WHERE
t1.agp_keywords NOT LIKE "%keyword1%" AND
t1.agp_keywords NOT LIKE "%keyword2%" AND
t1.agp_keywords_date BETWEEN (1369440000 AND 1369932432)
ORDER BY RAND() LIMIT 1
However this does not work correctly. Any help will be appreciated.
Try this, your original specifications were a bit confusing :(
SELECT keywords.agp_user_id,
keywords.agp_order_id,
keywords.agp_blog_id,
keywords.agp_keywords,
keywords.agp_keywords_date,
blogs.agp_name,
blogs.agp_url,
blogs.agp_username,
blogs.agp_password
FROM blogs
LEFT JOIN keywords
ON keywords.agp_blog_id = blogs.ID
AND keywords.agp_keywords NOT LIKE "%keyword1%"
AND keywords.agp_keywords NOT LIKE "%keyword2%"
AND FROM_UNIXTIME(keywords.agp_keywords_date) > (DATE_SUB(CURDATE(), INTERVAL 5 DAYS))
ORDER BY RAND() LIMIT 1

Categories