MySQL query SELECT FROM 2 tables, COUNT the most used - mysql

I have this 2 tables and I need to return the moset used office. Note: 1 office can be used by more than 1 guys and the column ido from TableB is populate from TableA
Probaly is a query with group by and desc limit 1
TableA
| ido| office | guy |
---------------------
| 1 | office1| guy1|
| 2 | office2| guy2|
| 3 | office1| guy3|
| 4 | office1| guy4|
| 5 | office5| guy5|
| 6 | office2| guy6|
TableB
| idb| vizit | ido|
---------------------
| 1 | date | 4 |
| 2 | date | 2 |
| 3 | date | 5 |
| 4 | date | 6 |
| 5 | date | 1 |
| 6 | date | 6 |
Thanks!

You were correct in that GROUP BY, LIMIT and DESC are useful here; it leads to a fairly straight forward query;
SELECT TableA.office
FROM TableA
JOIN TableB
ON TableA.ido = TableB.ido
GROUP BY TableA.office
ORDER BY COUNT(*) DESC
LIMIT 1
What it does is basically create rows with all valid combinations, counting the number of generated rows per office. A plain descending sort by that count will give you the most frequently used office.
An SQLfiddle to test with.

Related

Get rows with condition on last grouping row

I have table favourite_products with schema like below. I need to count how many people (account_id) like product with id = 12. But the condition is that person marked product as liked on last time.
In this example user with id = 1 marked product 12 as positive for the first time, but then he marked is a non-positive so this value shouldn't be returned. The following example should return 2 rows (for user_id = 5 and user_id = 8). I heard about window function but have mysql in version 5.7 and I can't upgrade it. Do you have some ideas how to write this query?
| id | user_id | product_id | positive |
| 1 | 1 | 12 | 1 |
| 2 | 1 | 12 | 0 |
| 3 | 1 | 15 | 1 |
| 4 | 5 | 12 | 1 |
| 5 | 5 | 12 | 1 |
| 6 | 11 | 18 | 1 |
| 7 | 8 | 12 | 1 |
| 8 | 8 | 12 | 1 |
Following approach should work for all the cases, including the case when a product was disliked and then liked again at the end.
In a Derived table, we can get the maximum id value for every user_id and product_id = 12. This result-set will be joined to the main table appropriately. This will fetch us the complete row (recent activity done by user for a product).
Now, we can consider only those users where the last activity is positive.
Query
SELECT fp.user_id
FROM favourite_products AS fp
JOIN (SELECT user_id,
Max(id) AS max_id
FROM favourite_products
WHERE product_id = 12
GROUP BY user_id) AS dt
ON dt.user_id = fp.user_id
AND dt.max_id = fp.id
AND fp.positive = 1;
Result
| user_id |
| ------- |
| 5 |
| 8 |
View on DB Fiddle

Selecting the most recent result from one table joining to another

I have two tables.
One table contains customer data, like name and email address. The other table contains a log of the status changes.
The status log table looks like this:
+-------------+------------+------------+
| customer_id | status | date |
+-------------+------------+------------+
| 1 | Bought | 2018-07-01 |
| 1 | Bought | 2018-07-02 |
| 2 | Ongoing | 2018-07-03 |
| 3 | Ongoing | 2018-07-04 |
| 1 | Not Bought | 2018-07-05 |
| 4 | Bought | 2018-07-06 |
| 4 | Not Bought | 2018-07-07 |
| 4 | Bought | 2018-07-08 | *
| 3 | Cancelled | 2018-07-09 |
+-------------+------------+------------+
And the customer data:
+-------------+------------+
| id | name | email |
+-------------+------------+
| 1 | Alex | alex#home |
| 2 | John | john#home |
| 3 | Simon | si#home |
| 4 | Philip | phil#home |
+-------------+------------+
I would like to select the customer's who have "Bought" in July (07). But exclude customers who's status has changed from "Bought" anything other most recently.
The result should be just one customer (Philip) - all the others have had their status change to something other than Bought most recently.
I have the following SQL:
SELECT
a.customer_id
FROM
statuslog a
WHERE
DATE(a.`date`) LIKE '2018-07-%'
AND a.status = 'Bought'
ORDER BY a.date DESC
LIMIT 1
But that is as far as I have got! The above query only returns one result, but essentially there could be more than one.
Any help is appreciated!
Here is an approach that uses a correlated subquery to get the most recent status record:
SELECT sl.customerid
FROM wwym_statuslog sl
WHERE sl.date = (SELECT MAX(sl2.date)
FROM wwym_statuslog sl2
WHERE sl2.customer_id = sl.customer_id AND
sl2.date >= '2018-07-01' AND
sl2.date < '2018-08-01'
) AND
sl.status = 'Bought'
ORDER BY sl.date DESC
LIMIT 1;
Notes:
Use meaningful table aliases! That is, abbreviations for the table names, rather than arbitrary letters such as a and b.
Use proper date arithmetic. LIKE is for strings. MySQL has lots of date functions that work.
In MySQL 8+, you would use ROW_NUMBER().

Get frequency of data from two columns via one SQL query

I have the table
_______________
| from | to |
| 1 | 2 |
| 2 | 2 |
| 1 | 2 |
| 3 | 2 |
Where from and to are countries.
I need to get top 10 countries met in from and to.
The result would be
________________
|country| count |
| 2 | 5 |
| 1 | 2 |
| 3 | 1 |
I reached what I need in two queries, but I am almost sure there is possibility to manage it with one.
Thanks in advance.
You want to use a UNION ALL and then GROUP BY using the union of from and to:
SELECT country, COUNT(*) AS count FROM
(SELECT from AS country FROM table_name
UNION ALL
SELECT to AS country FROM table_name)
GROUP BY country
ORDER BY count DESC
LIMIT 10

how to approach this in MySql query?

I want to select the data as per condition:I have a table with physician_key and corresponding quality score for a given month. I want to select count of distinct physicians with quality score 1,2.
For a month, there could be more entries for a physician_key and accordingly the quality assigned(on scale 1-7). I want to select only the count of those physicians which have quality (1,2) and if the same physician has quality >2 in given month, I don't want to count that physician.I want the information by product and month
I created an example table, since you didn't provide one:
mysql> select * from sales_mkt_rep_qual;
+-------------------+---------+-------+-------------------+
| GEO_PHYSICIAN_KEY | product | month | SALES_REP_QUALITY |
+-------------------+---------+-------+-------------------+
| 1 | a | 8 | 1 |
| 1 | a | 8 | 2 |
| 1 | a | 8 | 3 |
| 2 | b | 8 | 2 |
| 2 | b | 8 | 1 |
| 2 | b | 9 | 2 |
| 1 | a | 9 | 2 |
| 2 | b | 9 | 3 |
| 3 | a | 9 | 2 |
+-------------------+---------+-------+-------------------+
The query from your comment indeed gives an error:
SELECT COUNT(DISTINCT GEO_PHYSICIAN_KEY) AS encount_1to2,
product,MONTH
FROM sales_mkt_rep_qual
WHERE MAX(SALES_REP_QUALITY) = 2 ;
ERROR 1111 (HY000): Invalid use of group function
If you change that to:
SELECT DISTINCT geo_physician_key AS encount_1to2, product, month
FROM sales_mkt_rep_qual
WHERE (geo_physician_key,month,product)
NOT IN (
SELECT geo_physician_key, month, product
FROM sales_mkt_rep_qual
WHERE sales_rep_quality >2 );
you see the detailed result:
+--------------+---------+-------+
| encount_1to2 | product | month |
+--------------+---------+-------+
| 2 | b | 8 |
| 1 | a | 9 |
| 3 | a | 9 |
+--------------+---------+-------+
No, you can introduce the counting:
SELECT COUNT(distinct geo_physician_key ) AS no_of_physicians,product, month
FROM sales_mkt_rep_qual
WHERE (geo_physician_key,month,product)
NOT IN (
SELECT geo_physician_key, month, product
FROM sales_mkt_rep_qual WHERE sales_rep_quality >2 )
GROUP BY month, product;
+------------------+---------+-------+
| no_of_physicians | product | month |
+------------------+---------+-------+
| 1 | b | 8 |
| 2 | a | 9 |
+------------------+---------+-------+
If that still isn't what you are looking for, give more specific table structure and data example.
Try this:
SELECT count(DISTINCT physician_key)
FROM my_table
WHERE month = desired_month
AND max(quality) = 2
GROUP BY month
Actually I want the data to be like the output below:
+--------------+---------+-------+
| encount_1to2 | product | MONTH |
+--------------+---------+-------+
| 2 | b | 8 |
+--------------+---------+-------+
and for the criteria SALES_REP_QUALITY <= 2, isn't there a possibility that while selecting the distinct geo physician key, it might select out of first 2 considering it matches the criteria? Thats the reason I have used Thanix approach of max function with group by product and month, so that the aggregate function is applied on every product within a month

mysql select sum of rows by comparing two relations

I have data from tests with two lists of parts, called in and out. I need to select SUM of test values for each part after the last test where the part went in but didn't come out.
IN LIST OUT LIST TEST
+--------+-----------+ +--------+------------+ +------+-------+
| testid | in_partid | | testid | out_partid | | test | value |
+--------+-----------+ +--------+------------+ +------+-------+
| 1 | 10 | | 1 | 10 | | 1 | 1 |
| 1 | 20 | | 1 | 20 | | 2 | 10 |
| 2 | 10 | | 2 | 10 | | 3 | 100 |
| 2 | 20 | | | | | | |
| 3 | 10 | | 3 | 10 | | | |
| 3 | 20 | | 3 | 20 | | | |
+--------+-----------+ +--------+------------+ +------+-------+
SUM is pretty straightforward, but can I limit it to those rows where testid is greater than testid for the last inspection where part went in but not out?
In this example, part 10 should SUM all three test values, because it's included in all lists, but part 20 should only return value for test 3, as in test 2 it was not included in both in and out lists.
partid sum(value)
10 111
20 100
Can I do with with mysql, or do I need to include php in the mix?
I think your sample output is incorrect from your logic. I think partid 20 should return 101 as it is present in both lists for both tests 1 and 3. Assuming I'm right in that, this query should return the desired results
SELECT in_partid,SUM(value)
FROM (
SELECT DISTINCT in_partid,inl.testid
FROM in_list inl
INNER JOIN out_list outl ON in_partid=out_partid AND inl.testid=outl.testid
) as tests_passed
INNER JOIN tests ON tests_passed.testid=test
GROUP BY in_partid
EDIT: based on OP's comment my assumption above was wrong and was actually a requirement. Accordingly here is a query that I think fulfils the requirements:
SELECT tests_passed.in_partid,SUM(value)
FROM (
SELECT DISTINCT inl.in_partid,IFNULL(last_failed_test,0) as last_failed_test
FROM in_list inl LEFT JOIN (
SELECT in_partid,MAX(inl.testid) as last_failed_test
FROM in_list inl
LEFT JOIN out_list outl ON in_partid=out_partid AND inl.testid=outl.testid
WHERE outl.testid IS NULL
GROUP BY in_partid
) AS last_passed
ON inl.in_partid=last_passed.in_partid
) as tests_passed
INNER JOIN tests ON tests_passed.last_failed_test<test
GROUP BY tests_passed.in_partid
This returns the sample results given above for the sample data supplied.