MYSQL subquery count - mysql

I have a q MySQL query that finds part numbers and returns the count; I need to figure out how to get the query to output by part number counts
this my query now
select count(partnumber)
from db1
where part number REGEXP '6270|6269|6266'
output part number 30
what I would like is the output to look like this,
part numbers count
6270 | 20
6269 | 10
6266 | 5

If I understand correctly, this is a better way to write the query:
select partnumber, count(*)
from db1 where partnumber in (6270, 6269, 6266)
group by partnumber;
This in expression is not exactly the same as your regular expression (the equivalent regular expression would be '^6270|6269|6266$'). If you really want partial matches, then you should use the regular expression.
For exact matches, in is better because (1) it is standard SQL; (2) the types are correct in the comparison; and (3) it optimizes better.

Related

Mysql: subtracting does not let me go below 0

So I have a query that looks like this:
select name_of_restaurant, diners - avg(diners)
from table
group by name_of_restaurant;
name_of_restaurant is a VARCHAR(50) and diners is an INT.
what I am expecting it to do is this:
name_of_restaurant diners - avg(diners)
merchant1 -140
merchant2 -200
merchant3 -2
but instead I get:
name_of_restaurant diners - avg(diners)
merchant1 0.0000
merchant2 0.0000
merchant3 0.0000
How can I make it so that I get negative values in my result? What is wrong here? Thanks in advance for any assistance.
The GROUP BY expression that you're using here is malformed. diners is neither part of the grouping nor an aggregate function, so it's technically invalid to refer to it in the SELECT statement, as there may be multiple different values for that column in a single group. MySQL silently ignores this and uses an arbitrary value from the group.
(It's an unfortunate quirk of MySQL that this is even allowed. See "Why does MySQL allow "group by" queries WITHOUT aggregate functions?" for some discussion.)
In any case, from what you're describing here, I don't think you actually want a GROUP BY at all; what it sounds like you're trying to do is compare each row's diners with the overall average, not the average for that row or group. If that's the case, what you'd have to do is something along the lines of:
SELECT
name_of_restaurant,
diners - (SELECT AVG(diners) FROM table)
FROM table

MS Access count query does not produce wanted results

I have a table (tblExam) showing exam data score designed as follow:
Exam Name: String
Score: number(pecent)
Basically I am trying to pull the records by Exam name where the score are less than a specific amount (0.695 in my case).
I am using the following statement to get the results:
SELECT DISTINCTROW tblExam.name, Count(tblExam.name) AS CountOfName
FROM tblExam WHERE (((tblExam.Score)<0.695))
GROUP BY tblExam.name;
This works fine but does not display the exam that have 0 records more than 0.695; in other words I am getting this:
Exam Name count
firstExam 2
secondExam 1
thirdExam 3
The count of 0 and any exams with score above 0.695 do not show up. What I would like is something like this:
Exam Name count
firstExam 2
secondExam 1
thirdExam 3
fourthExam 0
fifthExam 0
sixthExam 2
.
..
.etc...
I hope that I am making sense here. I think that I need somekind of LEFT JOIN to display all of the exam name but I can not come up with the proper syntax.
It seems you want to display all name groups and, within each group, the count of Score < 0.695. So I think you should move < 0.695 from the WHERE to the Count() expression --- actually remove the WHERE clause.
SELECT
e.name,
Count(IIf(e.Score < 0.695, 1, Null)) AS CountOfName
FROM tblExam AS e
GROUP BY e.name;
That works because Count() counts only non-Null values. You could use Sum() instead of Count() if that seems clearer:
Sum(IIf(e.Score < 0.695, 1, 0)) AS CountOfName
Note DISTINCTROW is not useful in a GROUP BY query, because the grouping makes the rows unique without it. So I removed DISTINCTROW from the query.
Do I detect a contradiction? The query calls for results <0.695 but your text says you are also looking for results >0.695. Perhaps I don't understand. Does this give you what you are looking for:
SELECT DISTINCTROW tblExam.ExamName, Count(tblExam.ExamName) AS CountOfExamName
FROM tblExam
WHERE (((tblExam.Score)<0.695 Or (tblExam.Score)>0.695))
GROUP BY tblExam.ExamName;

MS Access - adding values

I have a simple table from two fields, words, frequency...
- Words Frequncy
- ABC 5
- DEF 7
- GHI 9
- ABC 3
- DEF 2
- GHI 1
The words are repeated with different frequencies and I want to sum the Frequncy values for each word to
- ABC 8
- DEF 9
- GHI 10
in a query.
What you need is a GROUP BY clause
SELECT Words, SUM(frequency) AS TotalFrequency
FROM the_table
GROUP BY Words
ORDER BY Words;
The GROUP BY clause must list all the columns used in the select list to which no aggregate function (like MIN, MAX, AVG or SUM) is applied.
The column name generated for expressions is not defined. In Access, for instance, it depends on the language version of Access. The name might be SumOfFrequency in English but SummeVonFrequency in German. An application working on one PC might fail on another one. Therefore I suggest defining a column name explicitly with expr AS column_name.
You need a group by clause. What this clause does is to, for lack of a better word, group the result for each distinct value in the column(s) specified in it. Then, aggregate functions (like sum) can be applied separately for each group. So, in your use case, you'd want to group the rows per value in Words and then sum each group's Frequency:
SELECT Words, SUM(Frequency)
FROM MyTable
GROUP BY Words

MySQL Sum and Case Query

I create a ReportViewer with VB.NET connecting to a MySQL database. The data appears like below.
IdProduct Quantity TotalPrice OrderDate
0001 1 10 29/09/2014
0002 2 40 29/09/2014
0001 4 40 29/09/2014
0001 2 20 29/09/2014
0001 2 20 29/09/2014
Based on the records above, I'd like the result to appear like below
0001 0002
9 2
90 40
What is Query Sum Case the best use here? Thanks in advance.
NOTE: It's not possible for a query to "dynamically" alter the number or datatype of the columns returned, those must be specified at the time the SQL text is parsed.
To return the specified resultset with a query, you could do something like this:
SELECT SUM(IF(t.IdProduct='0001',t.Quantity,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.Quantity,NULL)) AS `0002`
FROM mytable t
UNION ALL
SELECT SUM(IF(t.IdProduct='0001',t.TotalPrice,NULL)) AS `0001`
, SUM(IF(t.IdProduct='0002',t.TotalPrice,NULL)) AS `0002`
FROM mytable t
Note that the datatypes returned by the two queries will need to be compatible. This won't be a problem if Quantity and TotalPrice are both defined as integer.
Also, there's no specific guarantee that the "Quantity" row will be before the "TotalPrice" row; we observe that behavior, and it's unlikely that it will ever be different. But, to have a guarantee, we'd need an ORDER BY clause. So, including an additional discriminator column (a literal in the SELECT list of each query), that would give us something we could ORDER BY.
Note that it's not possible to have this single query dynamically create another column for IdProduct '0003'. We'd need to add that to the SELECT list of each query.
We could do this in two steps, using a query to get the list of distinct IdProduct, and then use that to dynamically create the query we need.
BUT... with all that said... we don't want to do that.
The normative pattern would be to return Quantity and TotalPrice as two separate columns, along with the IdProduct as another column. For example, the result returned by this statement:
SELECT t.IdProduct
, SUM(t.Quantity) AS `Quantity`
, SUM(t.TotalPrice) AS `TotalPrice`
FROM mytable t
GROUP BY t.IdProduct
And then the client application would be responsible for transforming that resultset into the desired display representation.
We don't want to push that job (of transforming the result into a display representation) into the SQL.
select idproduct, sum(quantity), sum(totalprice)
from your_table
group by idproduct

Grouping timestamps in MySQL with PHP

I want to log certain activities in MySql with a timecode using time(). Now I'm accumulating thousands of records, I want to output the data by sets of hours/days/months etc.
What would be the suggested method for grouping time codes in MySQL?
Example data:
1248651289
1248651299
1248651386
1248651588
1248651647
1248651700
1248651707
1248651737
1248651808
1248652269
Example code:
$sql = "SELECT COUNT(timecode) FROM timecodeTable";
//GROUP BY round(timecode/3600, 1) //group by hour??
Edit:
There's two groupings that can be made so I should make that clearer: The 24 hours in the day can be grouped but I'm more interested in grouping over time so returning 365 results for each year the tracking is in place, so total's for each day passed, then being able to select a range of dates and see more details on hours/minutes accessed over those times selected.
This is why I've titled it as using PHP, as I'd expect this might be easier with a PHP loop to generate the hours/days etc?
Peter
SELECT COUNT(*), HOUR(timecode)
FROM timecodeTable
GROUP BY HOUR(timecode);
Your result set, given the above data, would look as such:
+----------+----------------+
| COUNT(*) | HOUR(timecode) |
+----------+----------------+
| 10 | 18 |
+----------+----------------+
Many more related functions can be found here.
Edit
After doing some tests of my own based on the output of your comment I determined that your database is in a state of epic fail. :) You're using INT's as TIMESTAMPs. This is never a good idea. There's no justifiable reason to use an INT in place of TIMESTAMP/DATETIME.
That said, you'd have to modify my above example as follows:
SELECT COUNT(*), HOUR(FROM_UNIXTIME(timecode))
FROM timecodeTable
GROUP BY HOUR(FROM_UNIXTIME(timecode));
Edit 2
You can use additional GROUP BY clauses to achieve this:
SELECT
COUNT(*),
YEAR(timecode),
DAYOFYEAR(timecode),
HOUR(timecode)
FROM timecodeTable
GROUP BY YEAR(timecode), DAYOFYEAR(timecode), HOUR(timecode);
Note, I omitted the FROM_UNIXTIME() for brevity.