MySQL: Count two things in one query? - mysql

I have a "boolean" column in one of my tables (value is either 0 or 1).
I need to get two counts: The number of rows that have the boolean set to 0 and the number of rows that have it set to 1. Currently I have two queries: One to count the 1's and the other to count the 0's.
Is MySQL traversing the entire table when counting rows with a WHERE condition? I'm wondering if there's a single query that would allow two counters based on different conditions?
Or is there a way to get the total count along side the WHERE conditioned count? This would be enough as I'd only have to subtract one count from the other (due to the boolean nature of the column). There are no NULL values.
Thanks.

You could group your records by your boolean column and get count for each group.
SELECT bool_column, COUNT(bool_column) FROM your_table
WHERE your_conditions
GROUP BY bool_column
This will obviously work not only for bool columns but also with other data types if you need that.

Try this one:
SELECT
SUM(your_field) as positive_count,
SUM(IF(your_field, 0, 1)) as negative_count
FROM thetable

If they are all either 0 or 1 and you dont mind 2 rows as result you can group by that field and do a count like so:
select field, count(field)
from table
group by field

A simple group clause should do the trick :
SELECT boolField, COUNT(boolField)
FROM myTable
GROUP BY boolField

Related

combine duplicate records rows in sql into one row

I have duplicate records in one sql table . The rows has the same id but different values in different fields. how I can combine or merge those two rows or more into one row. Please help,
You can group those rows on certain fields by specifying a GROUP BY clause.
In your case you would group on the ID column. For the columns you select in the SELECT clause that are not specified in the GROUP BY clause (i.e. columns other than ID), you will have to apply an aggregate function (e.g. SUM, MAX, MIN, ...).
Edit - Simplified example based on your image:
SELECT
MasterID,
CUSTNAME=MIN(CUSTNAME),
ER1=MIN(ER1),
ER1_BU=MIN(ER1_BU)
-- For the other fields, the idea is the same
FROM
your_table
GROUP BY
MasterID
ORDER BY
MasterID;
This example takes for each field the minimum of the fields for a particular MasterID. You did not really define what you mean by "merge". Perhaps you want the result to be a particular merge, you will have to clarify further if this example doesn't "merge" the rows like you want.

func.count(distinct(...)) does not give the same result as distinct().count()

I have a column with null entries, e.g. the possible values in this column are None, 1, 2, 3
When I count the number of unique entries in the column with session.query(func.count(distinct(Entry.col))).scalar() I get back '3'.
But when I perform the count with session.query(Entry.col).distinct().count(), I get back '4'.
Why does the latter method count the None, but the first doesn't?
In the first case, the resulting query will look like this:
SELECT COUNT(DISTINCT(col)) FROM Entry
... and, as you probably already know, COUNT here won't actually count the NULL values.
In the second case, however, the query is different, as shown in the doc:
SELECT count(1) AS count_1 FROM (
SELECT DISTINCT(col) FROM Entry
) AS anon_1
Now that just counts the total number of the rows returned by SELECT DISTINCT query (which is 4 - NULL is included in the output of DISTINCT queries).
The reason is simple: query.count purpose is to return the number of rows the query would have returned if run without count clause. This method doesn't give you control over which columns should be used to count - that's what func.count(...) is for.
MySQL COUNT doesn't count NULL values, so if you are counting values by a field that has NULL values, that rows won't be counted by COUNT.
DISTINCT returns just number of different values so NULL is included.

How do I use distinct for a column along with a where clause in sql server 2008?

I want to get the distinct value of a particular column however duplicity is not properly managed if more than 3 columns are selected.
The query is:
SELECT DISTINCT
ShoppingSessionId, userid
FROM
dbo.tbl_ShoppingCart
GROUP BY
ShoppingSessionId, userid
HAVING
userid = 7
This query produces correct result, but if we add another column then result is wrong.
Please help me as I want to use the ShoppingSessionId as a distinct, except when I want to use all the columns from the table, including with the where clause .
How can I do that?
The DISTINCT keyword applies to the entire row, never to a column.
Presently DISTINCT is not needed at all, because your script already makes sure that ShoppingSession is distinct: by specifying the column in GROUP BY and filtering on the other grouping column (userid).
When you add a third column to GROUP BY and it results in duplicated ShoppingSession, it means that some ShoppingSession values are associated with many different values of the added column.
If you want ShoppingSession to remain distinct after including that third column, you should decide which values of the the added column should be left in the output and which should be discarded. This is called aggregating. You could apply the MAX() function to that column, or MIN() or any other suitable aggregate function. Note that the column should not be included in GROUP BY in this case.
Here's an illustration of what I'm talking about:
SELECT
ShoppingSessionId,
userid,
MAX(YourThirdColumn) AS YourThirdColumn
FROM dbo.tbl_ShoppingCart
GROUP BY
ShoppingSessionId,
userid
HAVING userid = 7
There's one more note on your query. The HAVING clause is typically used for filtering on aggregated columns. If your filter does not involve aggregated columns, you'll be better off using the WHERE clause instead:
SELECT
ShoppingSessionId,
userid,
MAX(YourThirdColumn) AS YourThirdColumn
FROM dbo.tbl_ShoppingCart
WHERE userid = 7
GROUP BY
ShoppingSessionId,
userid
Although both queries would produce identical results, their efficiency would be different, because the first query would have to pull all rows, group/aggregate them, then discard all rows except userid = 7, but the second one would discard rows first and only then group/aggregate the remaining, which is much more efficient.
You could go even further and exclude the userid column from GROUP BY and pull its value with an aggregate function:
SELECT
ShoppingSessionId,
MAX(userid) AS userid,
MAX(YourThirdColumn) AS YourThirdColumn
FROM dbo.tbl_ShoppingCart
WHERE userid = 7
GROUP BY
ShoppingSessionId
Since all userid values in your output are supposed to contain 7 (because that's in your filter), you can just pick a maximum value per every ShoppingSession, knowing that it'll always be 7.

Data compaction in (My)SQL

I've got a table with 2 columns. The first one is the auto-increment one and the second holds some numeric value. I need to group rows in such a way: get N consecutive rows (using the auto-increment field), count average of corresponding numeric values and put this 1 new line to the other table. Can anyone help me with the GROUP BY statement?
no need for group by ?
SELECT floor(id / 5) cnt,avg(2ndcol) from <table> group by cnt;
This will get groups of 5 rows and return the average of 2ndcol. Example http://www.sqlize.com/y4mTuDF1Cy
avg() docs
edited as per comments

SQL combine COUNT and AVG query with SELECT

I need to get the average rating and the total number of ratings for a particular user and then select all single ratings (rating_value, rating_text, creator) as well:
$rating_query = mysql_query("SELECT COUNT(1) as rating_count
,AVG(rating_value), rating_value, rating_text, creator
FROM user_rating WHERE rated_user = $user_id");
This query would return the COUNT(1) result and the AVG(rating_value) for every row, but I only need those values once.
Is there any way to do this without making 2 separate queries?
There may be a trick I'm not aware of, but I don't think that's possible to do in a single query. You could try using a GROUP BY clause if that would make sense for you, but I'm guessing it probably doesn't from the column names you're using. Any relation requires a single atomic value at any given row and column, even if that value is null. What you are requesting is that columns 1 and 2 in every row but the first have no value, and again I don't think this is possible.