I have a problem with my queries. I have now 2 queries and that works fine. But when I want to add another query with a PIVOT, it doesn't work. I have tried a lot of things but nothing works..
This is my first two queries
$query = "SET SQL_BIG_SELECTS = 1;";
$query .= "SELECT * FROM datakram, datakram2, datakram3 WHERE datakram.NAME = datakram2.NAME AND datakram2.NAME = datakram3.NAME"
And I want to add a PIVOT for table "datakram4". But I want only the rows where the NAME is equal to the NAME in the others tables. Without the PIVOT it works..
My PIVOT code.
SELECT `name` ,
MAX( CASE WHEN `year` =2017 THEN `income` ELSE 0 END ) AS INCOME_2017,
MAX( CASE WHEN `year` =2017 THEN `expense` ELSE 0 END ) AS EXPENSE_2017,
MAX( CASE WHEN `year` =2016 THEN `income` ELSE 0 END ) AS INCOME_2016,
MAX( CASE WHEN `year` =2016 THEN `expense` ELSE 0 END ) AS EXPENSE_2016
FROM `test_data` GROUP BY `name`
I use multi_query for my php script.
Simply join the queries:
SELECT d4.*
FROM datakram d1
INNER JOIN datakram2 d2
ON d1.`NAME` = d2.`NAME`
INNER JOIN datakram3 d3
ON d2.`NAME` = d3.`NAME`
INNER JOIN
(SELECT `name` ,
MAX(CASE WHEN `year`=2017 THEN `income` ELSE 0 END) AS INCOME_2017,
MAX(CASE WHEN `year`=2017 THEN `expense` ELSE 0 END) AS EXPENSE_2017,
MAX(CASE WHEN `year`=2016 THEN `income` ELSE 0 END) AS INCOME_2016,
MAX(CASE WHEN `year`=2016 THEN `expense` ELSE 0 END) AS EXPENSE_2016
FROM `test_data`
GROUP BY `name`
) d4
ON d3.`NAME` = d4.`name`
A simple way is to filter in the WHERE clause:
SELECT `name` ,
MAX(CASE WHEN `year` = 2017 THEN `income` ELSE 0 END) AS INCOME_2017,
MAX(CASE WHEN `year` = 2017 THEN `expense` ELSE 0 END) AS EXPENSE_2017,
MAX(CASE WHEN `year` = 2016 THEN `income` ELSE 0 END) AS INCOME_2016,
MAX(CASE WHEN `year` = 2016 THEN `expense` ELSE 0 END) AS EXPENSE_2016
FROM `test_data` td
WHERE EXISTS (SELECT 1 FROM FROM datakram d WHERE d.name = td.NAME) AND
EXISTS (SELECT 1 FROM FROM datakram2 d WHERE d.name = td.NAME) AND
EXISTS (SELECT 1 FROM FROM datakram3 d WHERE d.name = td.NAME)
GROUP BY `name` ;
Related
Why DISTINCT UID doesn't work in my code below?
$q = mysql_fetch_array(mysql_query("SELECT COUNT(DISTINCT UID) AS TOTAL,
SUM(CASE WHEN SYSTEM = 'Android' THEN 1 ELSE 0 END) AS A,
SUM(CASE WHEN SYSTEM = 'IOS' THEN 1 ELSE 0 END) AS I,
SUM(CASE WHEN SYSTEM = 'Windows' THEN 1 ELSE 0 END) AS W FROM user_visits"));
The query returns all items from the database selected even I put DISTINCT UID or *. Same result.
The distinct keyword is supposed to be outside like below,
SELECT DISTINCT column1, column2, ...
FROM table_name;
?
Also, you are trying to sum few things, It should be something like below,
SELECT UID, COUNT(UID) AS TOTAL,
SUM(CASE WHEN SYSTEM = 'Android' THEN 1 ELSE 0 END) AS A,
SUM(CASE WHEN SYSTEM = 'IOS' THEN 1 ELSE 0 END) AS I,
SUM(CASE WHEN SYSTEM = 'Windows' THEN 1 ELSE 0 END) AS W FROM user_visits
GROUP BY UID
with aggregate (group by)
I want to create an output table that is a combination of the two input tables, as shown below. Table 1 and table 2 are MySQL tables. Output is the desired table view.
Please hlep me to billd this output from table1 and table2 (mysql)
You can use conditional aggregation with UNION ALL for this:
SELECT t1.acc_no, t1.name,
SUM(CASE WHEN t2.`date` = '2016-06-01' THEN amount END) AS '2016-06-01',
SUM(CASE WHEN t2.`date` = '2016-06-02' THEN amount END) AS '2016-06-02',
SUM(CASE WHEN t2.`date` = '2016-06-03' THEN amount END) AS '2016-06-03',
SUM(amount) AS 'Total'
FROM table1 AS t1
LEFT JOIN table2 AS t2 ON t1.acc_no = t2.acc_no
UNION ALL
SELECT 'Total', null,
SUM(CASE WHEN t2.`date` = '2016-06-01' THEN amount END) AS '2016-06-01',
SUM(CASE WHEN t2.`date` = '2016-06-02' THEN amount END) AS '2016-06-02',
SUM(CASE WHEN t2.`date` = '2016-06-03' THEN amount END) AS '2016-06-03',
SUM(amount) AS 'Total'
FROM table2
I am using this code to get the data of a team
SELECT `in_standings`.*, `in_teams`.`name` as team_name, `in_teams`.`logo` as team_logo, `in_teams`.`shortcode` as team_shortcode, lr.*, in_teams.id as team_id
FROM `in_standings` daa
LEFT JOIN `in_teams` ON `in_standings`.`team_id`= `in_teams`.`id`
left join
(SELECT team1_id,daa.team_id as teamID,
MAX(CASE WHEN rn = 1 THEN winning_team END) AS result1,
MAX(CASE WHEN rn = 2 THEN winning_team END) AS result2,
MAX(CASE WHEN rn = 3 THEN winning_team END) AS result3,
MAX(CASE WHEN rn = 4 THEN winning_team END) AS result4,
MAX(CASE WHEN rn = 5 THEN winning_team END) AS result5
FROM (
SELECT team1_id, winning_team,
#row_number := #row_number + 1 AS rn
FROM in_games
CROSS JOIN (SELECT #row_number := 0) AS vars
WHERE team1_id = teamID <!-- here is problem -->
) AS t) as lr on lr.team1_id=in_standings.team_id
WHERE `in_standings`.`division_id` = '21'
ORDER BY `in_standings`.`points` DESC
My sub query where i comment is not getting the team_id by which i want to set the result of last 5 matchs in a same row.
Could anyone solve where is the problem?
I have a table in my database named contacts and a table named views.
On the table contacts I have the following fields:
id
status
first_name
last_name
The status can be cold, prospect or lost.
On the table views I have the following fields:
user_id
art_views
art_title
The relation between those 2 tables is id and user_id.
I need a query to make a new html table with the following columns:
art_title
cold
prospect
lost
Now I have the following query (UPDATED):
SELECT
v.art_title,
SUM(CASE c.status WHEN 'cold' THEN v.art_views ELSE 0 END) cold,
SUM(CASE c.status WHEN 'prospect' THEN v.art_views ELSE 0 END) prospect,
SUM(CASE c.status WHEN 'lost' THEN v.art_views ELSE 0 END) lost
FROM views v
JOIN contacts c ON v.user_id = c.id
GROUP BY v.art_title
This query is working now (thanks to Gerv) but i still have users who don't have a status. So i leave the field user_id in the table 'views' empty. How can i change the query for those users so i can count them also?
I tried to: SUM(CASE v.user_id WHEN ' ' THEN v.art_views ELSE 0 END) test,
but with no result here.
You can switch the logic by selecting from the views table and joining de contacts table.
Below query will pivot the status with a CASE clause
SELECT
v.art_title,
SUM(CASE c.status WHEN 'cold' THEN v.art_views ELSE 0 END) cold,
SUM(CASE c.status WHEN 'prospect' THEN v.art_views ELSE 0 END) prospect,
SUM(CASE c.status WHEN 'lost' THEN v.art_views ELSE 0 END) lost,
SUM(CASE c.status WHEN NULL THEN v.art_views ELSE 0 END) no_user
FROM views v
LEFT JOIN contacts c ON v.user_id = c.id
GROUP BY v.art_title
ORDER BY (cold+lost+prospect+no_user) DESC
LIMIT 10
Try
SELECT art_title, SUM(art_views), status FROM contacts AS c INNER JOIN views AS v ON v.user_id = c.id GROUP BY v.art_title, c.status
suppose this
user table:
[id] [mail] [pass]
happen table:
[id] [uid] [date] [content]
vote table
[uid] [hid] [type] [datetime]
1 user can have 0 or more happen, 1 happen can have 0 or more votes..
I want to get the total number of votes for a specific happen
SELECT
H.*,
SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
happens H
LEFT JOIN
votes AS V
ON V.hid = H.id
WHERE
H.uid = :uid
the problem is that if no votes is associated on a happen I get a null row from mysql, not EMPTY but NULL
how can I avoid this null result?
[edit]
some try:
basic
SELECT H.* FROM happens H LEFT JOIN votes AS V ON V.hid = H.id WHERE H.uid = '178d937'
result -> empty
All other try with the SUM, COUNT, HAVING ect ect gives:
[id] [uid] [what] [latitude] [longitude] [date] [time] [hide] [upvotes] [downvotes]
NULL NULL NULL NULL NULL NULL NULL NULL 0 0
Use HAVING to check for the null
SELECT
H.*,
SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
happens H
LEFT JOIN
votes AS V
ON V.hid = H.id
WHERE
H.uid = :uid
HAVING upvotes IS NOT NULL
SELECT H.*,
SUM(IFNULL(V.type = 'C', 0)) AS upvotes,
SUM(IFNULL(V.type = 'R', 0)) AS downvotes
If you change your LEFT JOIN to an INNER JOIN (or just JOIN) you will only get the happens records that have at least 1 associated record in the votes table:
SELECT
H.*,
SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
happens H
INNER JOIN
votes AS V
ON V.hid = H.id
WHERE
H.uid = :uid
Check out http://www.w3schools.com/sql/sql_join.asp for info on the different join types.
EDIT:
Ok, so to get all happens, but with 0 for those without votes try (add COALESCE):
SELECT
H.*,
COALESCE(SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END),0) AS upvotes,
COALESCE(SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END),0) AS downvotes
FROM
happens H
LEFT JOIN
votes AS V
ON V.hid = H.id
WHERE
H.uid = :uid
SELECT
H.*,
COALESCE(SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END), 0) AS upvotes,
COALESCE(SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END), 0) AS downvotes
Left Join will return all rows on the left and NULL values on the right if ON condition does not match.Use Inner Join.
solved using 2 statement
first select all happen
second select all votes for every happen and merging the values
here is the solution from my php happenModel class:
public function getUserHappensWithVotes() {
$selectQuery = <<<QUERY
SELECT
SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
votes V
WHERE
V.uid = :uid
AND
V.hid = :hid
QUERY;
// get all happen as array of class
$userHappens = $this->userHappens;
// empty container
$happenWithVotes = array();
foreach( $userHappens AS $happen ) {
$sql = $this->pdo->prepare( $selectQuery );
$sql->execute( array( ':uid'=>$happen->uid, ':hid'=>$happen->id ) );
// fetching the count of up and down votes of every happen
$votes = $sql->fetch( PDO::FETCH_ASSOC );
// merging happen class as array with votes
$happen = array_merge( (array) $happen, $votes );
// rebuild the userHappen array
$happenWithVotes[] = (object) $happen;
}
if ( $this->encoder ) {
return $this->encoder->setData( $this->parse( $happenWithVotes ) )->encode();
} else {
return $this->parse( $happenWithVotes );
}
}