Why does the total from my query results not add up? - mysql

I have three queries that get stats from the database, but the total does not add up correctly for my results. If I do the math myself this is what I get: // 440728 / 1128 = 390.72
However, the following is what is returned by my queries:
SELECT * FROM facebook_accts
WHERE user_id IN (SELECT id FROM `user_accts` WHERE owner_id = '121')
// returns 1128
SELECT sum(friend_count) FROM facebook_accts
WHERE user_id IN
(SELECT id FROM `user_accts` WHERE owner_id = '121')
// returns 440728
SELECT avg(friend_count) FROM facebook_accts
WHERE user_id IN
(SELECT id FROM `user_accts` WHERE owner_id = '121')
// returns 392.11 (number formatted to two decimal places by php)

this may be happening because of column friend_count having some NULL values because SUM and AVG sunctions ignore NULL values. see here.

I guess the 1128 rows contain NULL values (which AVG and SUM ignore).

Related

calculate percentage of distinct records depending on its 'status' using stored procedure

I have a table site_level,I need to work on columns named 'market',status, id.
for column market , I want to calculate percentage of id depending on its status as completion or rejection.
id column may have duplicate rows.so i need distinct rows.
Ex. market 'germany' will have several id's with status accepted or rejected.
i want to calculate percentage like (total distinct id for market germany)/ (distinct id with status as accepted for germany)
I need the query result in below format.
market / count__id_accepted / count_id_rejected/ percentage_accepted / percentage_rejected
select result1.market AS market,count(result1.unique_id) AS distinct unique_id,count(result1.status='accepted' or null) as'count_acc',count(result1.status='accepted' or null)*100/count(result1.unique_id) as 'perc_accepted',count(result1.status='rejected' or null) as 'count_rej',count(result1.status='rejected' or null)*100/count(result1.unique_id) as 'perc_rejected',
count(result1.status='to be performed' or null) as 'count_tbp',count(result1.status='to be performed' or null)*100/count(result1.unique_id) as 'perc_tbp',count(result1.status='incomplete test' or null) as 'count_inco',
count(result1.status='incomplete test' or null)*100/count(result1.unique_id) as 'perc_inco' from result1
group by result1.market

MySql query counting and assigning constants based on ranges

There's one table
MEMBERS:
id - member id,
dt_activate - member's join unix datetime,
id_inviter - member's id who did invite current member (0 if member joined on his own)
Trying to write a Select that would return the following multiple rows result, where each row would contain:
(1) id - member id;
(2) cnt - count of rows in MEMBERS table where this "id" appeared in id_inviter field and at the same time the dt_activate should be between constants dt_start and dt_end;
(3) img - "imageA.gif" if cnt is between 10-19, "imageB.gif" if between 20-29, "imageC.gif" if greater than 29;
(4) reward - constant X if cnt is between 10-19, Y if between 20-29, Z if greater than 29
Unfortunately my knowledge doesn't let me go past the simple selects like:
SELECT id_inviter, sum(1) AS cnt
FROM members
WHERE dt_activate>=$dt_start AND dt_activate<=$dt_end
GROUP BY id_inviter
HAVING cnt>=10
Estimated record count for MEMBERS table might be between 10-50k.
Please help to achieve the result described above, thank you.
Try this one:
SELECT id_inviter, count (*) AS cnt,
case when count (*) <20 then 'imageA.gif'
when count (*) <30THEN 'imageB.gif' else 'imageC.gif' end as image,
case when count (*) <20 then 'X'
when count (*) <30 THEN 'Y' else 'Z' end as reward
FROM members
WHERE dt_activate>=$dt_start AND dt_activate<=$dt_end
GROUP BY id_inviter
HAVING cnt>=10

mySQL count occurances of value on multiple fields. How?

I have a table with 5 fields. Each field can store a number from 1 - 59.
Similar to countif in Excel, how do I count the number of times a number from 1 - 59 shows up in all 5 fields?
Here's an example for the count of occurances for the number 1 in all five fields:
SELECT SUM(pick_1 = 1 OR pick_2 = 1 OR pick_3 = 1 OR pick_4 = 1 OR pick_5 = 1) AS total_count_1
FROM tbldraw
Hopefully I made sense.
There was an answer here that had a solution. I think this is just a variation.
Step1: Create a numbers table (1 field, called id, 59 records (values 1 -59))
Step2:
SELECT numbers_table.number as number
, COUNT(tbldraw.pk_record)
FROM numbers_table
LEFT JOIN tbldraw
ON numbers_table.number = tbldraw.pick_1
OR numbers_table.number = tbldraw.pick_2
OR numbers_table.number = tbldraw.pick_3
OR numbers_table.number = tbldraw.pick_4
OR numbers_table.number = tbldraw.pick_5
GROUP BY number
ORDER BY number
How about a two step process? Assuming a table called summary_table ( int id, int ttl), for each number you care about...
insert into summary_table values (1,
(select count(*)
from table
where field1 = 1 or field2 = 1 or field3 = 1 or field4 = 1 or field5 = 1))
do that 59 times, once for each value. You can use a loop in most cases. Then you can select from the summary_table
select *
from summary_table
order by id
That will do it. I leave the coversion of this SQL into a stored procedure for those that know what database is in use.
The ALL() function, which returns true if the preceding operator is true for all parameters, makes the query particularly elegant and succinct.
To find the count a particular number (eg 3):
select count(*)
from tbldraw
where 3 = all (pick_1, pick_2, pick_3, pick_4, pick_5)
To find the count of all such numbers:
select pick_1, count(*)
from tbldraw
where pick_1 = all (pick_2, pick_3, pick_4, pick_5)
group by pick_1

Why does this query returns no result?

I have two Tables, the table reseau_stream has different information about my a user post. A user can share the post of someone else. Table reseau_share makes that connexion (you have the detail of both table below). Now, if a user share someone else post, I have to order my query using the datetime of reseau_share.
I don't have alot of MySQL skills, but with some help, I finally ended up with the query below. It is working only if reseau_share has a row in it. If reseau_share is empty, the query return 0 result. I really don't understand why. Can anyone identify why ? Cheers.
Table reseau_stream
id user_id content datetime
1 100 Lorem Ipsum1 2013-03-04 19:35:02
2 100 Lorem Ipsum2 2013-03-04 12:35:02
Table reseau_share
id user_id target_id stream_id datetime
-------------------- EMPTY ------------------------
The query
SELECT reseau_stream.id,
reseau_stream.user_id,
reseau_stream.content,
IF(reseau_stream.user_id = 100, reseau_stream.datetime, reseau_share.datetime) as datetime
FROM reseau_stream, reseau_share
WHERE reseau_stream.id
IN (
SELECT id
FROM reseau_stream
WHERE user_id = 100
UNION
SELECT stream_id
FROM reseau_share
WHERE user_id = 100
) ORDER BY datetime DESC;
Basically it looks like you need a LEFT JOIN on reseau_share. Right now you have a FULL OUTER JOIN, which (a) is causing the zero rows as #diegoperini has pointed out and (b) probably isn't what you really want. It's unclear which column relates the two tables. I'll guess it's user_id:
SELECT
reseau_stream.id,
reseau_stream.user_id,
reseau_stream.content,
IF(reseau_stream.user_id = 100, reseau_stream.datetime, reseau_share.datetime) as datetime
FROM reseau_stream
LEFT JOIN reseau_share ON reseau_stream.user_id = reseau_share.user_id
WHERE reseau_stream.id
IN (
SELECT id
FROM reseau_stream
WHERE user_id = 100
UNION
SELECT stream_id -- or whatever
FROM reseau_share
WHERE user_id = 100
)
ORDER BY datetime DESC;
Cartesian product of a non empty set with an empty set is an empty set.
Multiple tables in a FROM statement uses above rule to join two tables which ends up with 0 results in your case.

Create view from two tables with different column names

Is there a way to create a view from two tables, where one of the columns is different among the two tables? The problem I am currently running into is that MYSQL is telling me that there is an undefined index - which makes perfect sense since, in half of the cases, the column won't exist.
Table Layout:
(post_rank_activity)
ID, post_id, ... date
(reply_rank_activity)
ID, rank_id, ... date
What I want the resulting view to look like:
ID | Post_id | Reply_id | Date
x x NULL x
x NULL x x
And the SQL:
$rankView = "Create or replace view userRank as (
select PRA.id, PRA.post_id, PRA.user_id, PRA.vote_up, PRA.rank_date
From post_rank_activity PRA)
union All
(select RRA.id, RRA.reply_id, RRA.user_id, RRA.vote_up, RRA.rank_date
from reply_rank_activity RRA)";
And the result I'm getting, instead of returning null, it's returning the value of "reply_id" for the "post_id" field and then shifting all of the other values over - see below:
ID | Post_id | Reply_id | Date
x x date val x
x reply val date val x
Any ideas?
Unions must contain the same columns in the same order across all parts. You should explicitly select/declare the null columns in each part of the union:
SELECT PRA.id, PRA.post_id, NULL AS reply_id, PRA.user_id, PRA.vote_up, PRA.rank_date
FROM post_rank_activity PRA
UNION All
SELECT RRA.id, NULL AS post_id, RRA.reply_id, RRA.user_id, RRA.vote_up, RRA.rank_date
FROM reply_rank_activity RRA
Your query should look like
select PRA.id, PRA.post_id, null as Reply_id PRA.rank_date
From post_rank_activity PRA
union All
select RRA.id, null as post_id, RRA.reply_id, RRA.rank_date
from reply_rank_activity RRA