Group by with where clause with having count equal to 1 - mysql

Objective: Find all rows where (1) the number of messages for a number is 1, and (2) the length of the message is less than 5 characters in length. I can do each separately, but having difficulty when I combine the two conditions in one SQL query.
Sample Database Table:
+-----+----------+----------+
| id | number | message |
+-----+----------+----------+
| 1 | 100 | Test |
| 2 | 100 | Testing |
| 3 | 100 | Testing |
| 4 | 200 | Test |
| 5 | 201 | Test |
| 6 | 201 | Test |
| 7 | 250 | Testing |
| 8 | 251 | Test |
| 9 | 300 | Testing |
| 10 | 300 | Testing |
+-----+----------+----------+
Should just return rows 200 and 251. Tried the following, but no luck:
SELECT * FROM `reports` WHERE LENGTH(message) < 5 GROUP BY number HAVING count(*) = '1'
Returns rows but rows contains counts > 1.

Ok, I made the wrong change a few hrs ago - this time I have the data just like yours. Ah, and NOW I see what you're having a problem with. You don't understand the order MySQL interprets your SELECT; it's first doing the WHERE to limit the results THEN it does the GROUP BY. Working as designed.

Related

SELECT, how to combine some rows as one, show rows with specific column value first and exclude a row

I have two tables, units and power.
Take a look at:
The power table:
+----+-------+
| id | power |
+----+-------+
| 1 | 2 |
| 2 | 4 |
| 3 | 6 |
| 4 | 8 |
+----+-------+
The units table:
+----+---------+----------+--------+----------+---+---+
| id | user_id | power_id | amount | group_id | x | y |
+----+---------+----------+--------+----------+---+---+
| 1 | 10 | 3 | 1000 | 0 | 1 | 1 |
| 2 | 10 | 3 | 1000 | 0 | 1 | 1 |
| 3 | 10 | 3 | 1000 | 0 | 1 | 1 |
| 4 | 11 | 2 | 100 | 4 | 1 | 1 |
| 5 | 11 | 2 | 100 | 4 | 1 | 1 |
| 6 | 11 | 1 | 100 | 4 | 1 | 1 |
| 7 | 12 | 4 | 1000 | 0 | 1 | 1 |
+----+---------+----------+--------+----------+---+---+
I want to get result looking like this:
+----------+--------------+-------------+----------+---------+--+
| units.id | total_amount | total_power | group_id | user_id | |
+----------+--------------+-------------+----------+---------+--+
| 3 | 1000 | 6000 | 0 | 10 | |
| 2 | 1000 | 6000 | 0 | 10 | |
| 4 | 300 | 1000 | 4 | 11 | |
| 7 | 1000 | 8000 | 0 | 12 | |
+----------+--------------+-------------+----------+---------+--+
Explanation:
Exclude a specific id, should work same for both a single row and a row which is a sum of multiple rows in the table. As you see, in the result set, row with id 1 was excluded. The id is provided by the app, I think it's better to do it in MySQL than PHP, because MySQL could just discard this row (I think), but with PHP it would have to do if() checking for every loop iteration, which seems less efficient.
Show the summed-rows row before single rows, every time.
Show user's units before other users', every time. You can see that when rows with user_id of 10 (imagine this user is the one seeing the page) appear first in my result set.
Show units with highest power first.
Show units with highest amount first.
Show units with highest id first.
The last(4.5.6) are sorted in regards to the priority of the result set, with 4th having the most of it.
I have this query:
SELECT units.id,
units.amount*power.power AS total_power,
Sum(units.amount) AS total_amount
FROM units
JOIN power
ON units.power_id = power.id
WHERE x = ?
AND y = 1
GROUP BY group_id
ORDER BY group_id desc, total_power desc, total_amount desc, units.id desc limit ?,?
But it combines all units where group_id is 0, however I want units with group_id=0 to be separate rows in the result set. How to do that? Thanks!
Edit: To answer #Linoff's question about how I determine which id to exclude, I exclude the 1 in the example because a user always will see the result set through accessing it with a unit_id, which, again, in my example happens to be 1. I hope it is clear now.
Edit: The user can access this list of units on page "index.php?page=unit/view&id=. Then I SELECT the entered id separately for the purpose of my app, and then SELECT the list. But as I already have data for the entered id (for instance, 1 in this case) I do not need to have them when I SELECT from the units and power.
#Anonymous, to answer your question 1, answer 1 is: all rows with same group_id (except 0 which is a not-a-group marker) are grouped and combined together, so rows which are id 4,5 and 6 which have identical group_id are combined. My problem is, I don't know how to exclude grouping for rows which are stand alone (no group marking) and how to sort the result so the rows with specified user_id are sorted first and grouped rows (4,5,6-turned-to-4) are also sorted first, but in user_id=10-first,user_id=??-second hierarchy, if this makes sense.

Finding values between 2 table columns

My Table structure is like this
-------------------------------------
| from | to | price | pid | type|
| 0 | 100 | 50 | 2 | new |
| 101 | 200 | 60 | 2 | new |
| 201 | 300 | 70 | 2 | new |
| 301 | 700 | 80 | 2 | new |
| 301 | 700 | 70 | 2 | old |
Now i am getting a value from that i have to get the price.
Let say my value is 106 then i should get the price 60.
My query is
SELECT * FROM tbl_goals WHERE from <= '106' AND to >='106' AND pid='2' AND type='new'
With this query i am getting all rows with type new
But in result i should get this row
| 101 | 200 | 60 | 2 | new |
Where i am doing wrong?
I would use BETWEEN here for the sake of readability:
SELECT *
FROM tbl_goals
WHERE 106 BETWEEN `from` AND `to` AND
pid = 2 AND
type = 'new'
Notes:
Don't put single quotes around numbers in your query when you want to treat them as numbers
Don't names your columns from or any other MySQL keyword, because then you might have to escape them everywhere in backticks to make the query work as intended

MySQL Query with select and grouping

I would like to select all of the client records that were submitted by 10 but not the client records where 20 was assigned as a representative. So my desire result would be 2 total records selected for client 2 and 3. 4 is excluded because 20 is part of that set. Any help is greatly appreciated.
+--------------+--------+----------------+
| Submitted_By | Client | Representative |
+--------------+--------+----------------+
| 10 | 2 | 15 |
| 10 | 2 | 16 |
| 10 | 2 | 17 |
| 10 | 3 | 15 |
| 10 | 3 | 16 |
| 10 | 3 | 19 |
| 10 | 4 | 15 |
| 10 | 4 | 16 |
| 10 | 4 | 17 |
| 10 | 4 | 20 |
+--------------+--------+----------------+
Tried
SELECT
Client,
Submitted_By,
Representative,
FROM
client
WHERE
Client = 10 AND Representative != 20
You could use a subquery like:
SELECT Client, Submitted_By, Representative
FROM client
WHERE Submitted_By = 10
AND Client NOT IN (SELECT Client FROM client WHERE Representative = 20)
You wrote you only want "2 total records" returned. Then a GROUP BY Client
statement can be used to return two rows, one for each client, from your provided example table.

Is it possible to create calculation rows from query results in MySQL?

I am trying to find a way to output a calculation row (or two) of an SQL search query, so I may see the raw results along with a calculation associated to them, either above or under the listing of raw results. For instance, I have the following data:
mysql> select * from data [where condition];
+----+--------+-----+--------+
| id | height | age | weight |
+----+--------+-----+--------+
| 1 | 65.2 | 45 | 45.23 |
| 2 | 63.1 | 47 | 0 |
| 3 | 59.2 | 37 | 38.1 |
| 4 | 59.8 | 39 | 36.4 |
| 5 | 63.4 | 37 | 38.1 |
| 6 | 72.1 | 34 | 2 |
| 7 | 100 | 50 | 20 |
+----+--------+-----+--------+
And what I want is to be able to perform any query to get all or a subset of this data, but have the resulting table give something like the following (with the summary/calculation output separate from the raw data, such as either above or below it):
mysql> query???
+--------+--------+------+--------+
| id | height | age | weight |
+--------+--------+------+--------+
| 1 | 65.2 | 45 | 45.23 |
| 2 | 63.1 | 47 | 0 |
| 3 | 59.2 | 37 | 38.1 |
| 4 | 59.8 | 39 | 36.4 |
| 5 | 63.4 | 37 | 38.1 |
| 6 | 72.1 | 34 | 2 |
| 7 | 100 | 50 | 20 |
+--------+--------+------+--------+
| STDDEV | 13.26 | 5.57 | 17.15 |
| COUNT | 7 | 7 | 7 |
| etc. | etc. | etc. | etc. |
+--------+--------+------+--------+
I've found some approaches such as this (http://www.sqlservercurry.com/2011/06/sql-server-row-summary-column-summary.html) that somewhat do it, but because the calculation acts on all rows it doesn't work well for some calculations (for instance, using stddev results in "0" for everything except the calculation row).
I can create a separate result of calculations such as the following, but it would be nice to have them somehow combined, such as shown above. In addition, the following only outputs one row of calculations, and it would be nice to have several rows of pertinent calculations.
select stddev(height), stddev(age), stddev(weight) from data [where condition];
The point here is to perform any search query and get an auto-generated preview of basic descriptive information from the results (deviations, counts, mean, etc.). Hopefully this can be done directly in SQL, without needing to use another language/API.
Combine your results with union. If you need the results in a particular order, then create a column containing the precedence and order by that column.
select id, height, age, weight, 0 sortorder
from data [where condition]
union all
select 'stdev count', stddev(height), stddev(age), stddev(weight), 1
from data [where condition]
order by sortorder

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.