Getting Distinct Value Counts Across Multiple Fields/Tables in One MySQL Query - mysql

I have a table called visits which contains the following
link_id, id, browser, country, referer
Now, this basically records visits of a certain link and inserts the browser, country and referer of whomever visted that link in a database
Now I need to show statistics for each link
I used the following query to get me all the browsers
SELECT browser, COUNT(browser) FROM visits GROUP BY browser
Which produced something like
Browser Count(Browser)
Internet Explorer | 5
Chrome | 3
Now this worked as expected for browsers only but I'm looking for a way to count all occurrences of referers, browsers and countries in one single query.
Is there a way to do this?

To count multiple, different occurence counts of values in the DB can very easily be done in just one query.
Keep in mind, the column header in SELECT COUNT(tablename) returns only one column, with only one numeric value. For every distinct value (from the GROUP BY clause), you have two columns: Value, Count. To count for different fields, you'll need three: Field, Value, Count, and if you want to count different fields in different tables, you'll need four: Table, Field, Value, Count.
Observe how I am using UNION below for two different tables:
SELECT
"Table1" AS TableName,
"Field1" AS Field,
Field1 AS Value,
COUNT(Field1) AS COUNT
FROM Table1
GROUP BY Value
UNION
SELECT
"Table2" as TableName,
"Field2" as Field,
Field2 as Value,
COUNT(Field2) AS COUNT
FROM Table2
GROUP BY Value
You'll notice I need to use aliases: "Table2" as TableName, this is because the UNION'd columns ought to have matching column headers.
So you can visualize what this returns, take a look:
+-------------------+----------------+----------+--------+
| TableName | Field | Value | COUNT |
+-------------------+----------------+----------+--------+
| ItemFee | PaymentType | | 228 |
| ItemFee | PaymentType | All | 1 |
| ItemFee | PaymentType | PaidOnly | 1 |
| Person | Presenter | | 692258 |
| Person | Presenter | N | 590 |
| Person | Presenter | Y | 8103 |
+-------------------+----------------+----------+--------+

Related

Joint values from different queries into one

I have 6 tables of data.
I have 2 different queries that produce a table like this
| PERCENTAGE | COMPANY | TYPE |
(the companies are always the same in all tables, the only thing that changes is the PERCENTAGE and the type). Each query gets the total_percentage of an given company for one of the 2 different types.
For example:
Query 1 result:
| PERCENTAGE | COMPANY | TYPE |
0.0213 | Apple | Phones
0.3452 | Microsoft | Phones
Query 2:
|PERCENTAGE | COMPANY | TYPE |
0.4243 | Apple | Computers
...
And the result is:
Result:
| SUMMED_TOTAL| COMPANY |
0.0213 + 0.4243 | Apple
...
The summed percentage rows wont sum > 1, dont worry.
What i'd like to do is get the TOTAL_PERCENTAGE, from all types (all 2 queries) summed by company.
Any idea of an query? Im a begginer so it's kinda hard. You can literally use the names to do the query.
Use union all and group by:
select company, type, sum(percentage)
from ((select company, type, percentage from query1) union all
(select company, type, percentage from query2)
) ct
group by company, type;

How to count distinct values from two columns into one number

The two tables I'm working on are these:
Submissions:
+----+------------+
| id | student_id |
+----+------------+
| 1 | 1 |
| 2 | 2 |
| 3 | 3 |
+----+------------+
Group_submissions:
+----+---------------+------------+
| id | submission_id | student_id |
+----+---------------+------------+
| 1 | 1 | 2 |
| 2 | 2 | 1 |
+----+---------------+------------+
Only one student actually makes the submission and goes into the submissions table while the others go to the group_submissions table(if the submission is a group submission)
I want to count the unique number of students that have made submission either as a group or alone
I want just the number to be returned in the end (3 based on the data on the tables above)
A student that is in the submissions table should not be counted twice if he is in the group_submission table and vice-versa.
Also students that only have done individual submissions(that are not in the group_submissions table) also should be counted regardless if the have ever been in a group submission
I'm already doing some other operations on these table in a query I'm building so if you can give me a solution based on joining these two tables that would help.
This is what i have tried:
count(distinct case when group_submissions.student_id is not null then group_submissions.student_id end) + count(distinct case when submissions.student_id is not null then submissions.student_id end)
But it gives me duplicates so if a student is in both tables he is counted two times.
Any ideas?
NOTE: This is a MySQL database.
I think you want union and a count:
select count(*)
from ((select student_id
from submissions
)
union -- on purpose to remove duplicates
(select student_id
from group_submissions
)
) s;
After listening to the clarification, I think it is not wise to force yourself to compute this using the join. You can instead make the count just a simple expression as the final outcome. Use UNION and then distinct will help for building such an expression.
OLD ANSWER BELOW THAT DOES NOT FIT THE PROBLEM:
Very simple fix is needed to your current version...
count(distinct case when group_submissions.student_id is not null then
group_submissions.student_id when assignment_submissions.student_id is
not null then assignment_submissions.student_id end)
Note:
your original expression is an addition between 2 case expressions, each with a single WHEN inside
now I turn it into a single case expression with 2 WHEN's```SQL

Add user defined value to a column in an sql query

I have an SQL query:
select DISTINCT shortname_chn from dim_channel;
The query returns me data for example:
| shortname_chn (VARCHAR) |
|__________________________|
| MTV |
| National Geographic|
| Discovery |
| ARY News |
How can I manipulate the SQL query so that I can add an additional row to the returned rows.
Following is the result I wish to get after running some query:
| shortname_chn (VARCHAR) |
|__________________________|
| MTV |
| National Geographic|
| Discovery |
| ARY News |
| ALL |
Where the last row "ALL" is user defined, not present in the database.
In the above mentioned regard, I researched and came across this question : How to add a user defined column with a single value to a SQL query but it targets the problem of adding a whole new column.
select DISTINCT shortname_chn from dim_channel
UNION
SELECT 'ALL'
You can simply do something like this by UNIONing with a query that returns your fake row, e.g.:
SELECT DISTINCT
shortname_chn
FROM dim_channel
UNION ALL
SELECT 'ALL' AS shortname_chn

SQL group by dates, simple select statement

INTRO: Given a table with a column 'time' of unique dates(or datetime) and another column with some random integer called 'users'.
I usually do a call as such:
select table.dates, count(table.dates)
from table
group by year(table.dates), month(table.dates)
order by table.dates desc
which will return the number of users per month, albeit in an unformatted way. (I know it's not the standard way, but I check my values and this seems to work)
Here is my problem:
DATA: a table with with non-unique year/month dates, and a corresponding user count on that row.
PROBLEM: I wish to sum the user counts for identical dates, and again show a user count for every month.
EDIT: Perhaps you can ignore the INTRO, and here is an example of the data I need to work with:
| Date |user count |
----------------------.-
|2015-01 | 9 |
|2014-09 | 5 |
|2014-09 | 2 |
|2014-08 | 5 |
|2014-09 | 7 |
|2014-08 | 2 |
|2014-07 | 3 |

How can I make two condition in having clause

I have a table similar to:
domain | file | Number
------------------------------------
aaa.com | aaa.com_1 | 111
bbb.com | bbb.com_1 | 222
ccc.com | ccc.com_2 | 111
ddd.com | ddd.com_1 | 222
eee.com | eee.com_1 | 333
I need to query the number of Domains that share the same Number and their File name ends with _1. I tried the following:
select count(domain) as 'sum domains', file
from table
group by Number
having
count(Number) >1 and File like '%\_1';
It gives me:
sum domains | file
------------------------------
2 | aaa.com
2 | bbb.com
I expected to see the following:
sum domains | file
------------------------------
1 | aaa.com
2 | bbb.com
Because the Number 111 appears once with File ends with _1 and _2, so it should count 1 only. How can I apply the 2 conditions that I stated earlier correctly ?
As documented under SELECT Syntax:
The HAVING clause is applied nearly last, just before items are sent to the client, with no optimization.
In other words, it is applied after the grouping operation has been performed (in contrast with WHERE, which is performed before any grouping operation). See WHERE vs HAVING.
Therefore, your current query first forms the resultset from the following:
SELECT COUNT(domain) AS `sum domains`, file
FROM `table`
GROUP BY Number
See it on sqlfiddle:
| SUM DOMAINS | FILE |
---------------------------
| 2 | aaa.com_1 |
| 2 | bbb.com_1 |
| 1 | eee.com_1 |
As you can see, the values selected for the file column are merely one of the values from each group—as documented under MySQL Extensions to GROUP BY:
The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate.
Your current query then proceeds to filter these results according to your HAVING clause:
HAVING COUNT(Number) > 1 AND file LIKE '%\_1'
With the values of file selected above, every single group matches on the second criterion; and the first two groups match on the first criterion. Therefore the results of the complete query are:
| SUM DOMAINS | FILE |
---------------------------
| 2 | aaa.com_1 |
| 2 | bbb.com_1 |
Following your comments above, you want to filter the records on file before grouping and then filter the resulting groups for those containing more than one match. Therefore use WHERE and HAVING respectively (and select Number instead of file to identify each group):
SELECT Number, COUNT(*) AS `sum domains`
FROM `table`
WHERE file LIKE '%\_1'
GROUP BY Number
HAVING `sum domains` > 1
See it on sqlfiddle:
| NUMBER | SUM DOMAINS |
------------------------
| 222 | 2 |
i am using by following
having ( SUM(qty) > 4 AND SUM(qty) < 15 )
You cannot have the file name in the SELECT statement if it is not also in the GROUP BY. You have to get your GROUP BY result than JOIN back to the original and add the filter logic like so:
SELECT *
FROM
(
select count(domain) as 'sum_domains', Number
from table
group by Number
having
count(Number) >1
) result
join table t on result.Number = t.Number
WHERE file like '%\_1'
Try the nested query below:
select count(domain) as 'sum domains', domain as fileName
from
(select domain, file from tableName
group by Number
having count(Number) >1) as temp
WHERE file like '%\_1';