Select count where two columns aren't equal to 0 - mysql

I have a table as below mentioned:
|----------------|-------------|-------------|
| a_id | m_id | e_id |
|----------------|-------------|-------------|
| 1 | 1 | 0 |
| 2 | 2 | 2 |
| 3 | 3 | 3 |
| 4 | 1 | 1 |
| 5 | 4 | 4 |
|----------------|-------------|-------------|
I need a query that performs the task that a_id should have either m_id or e_id not equal to 0.
So, I wrote the query as follows which returns count 5:
SELECT count(a_id) from ids where (e_id!=0 or m_id!=0)
I need a_id should have distinct m_id != 0. That should return count 4.

use count(distinct
select count(distinct m_id) from ids where e_id!=0 or m_id!=0

Related

Get those items which are ordered after they have been delivered

I have two tables, namely itemOrders and itemDelivered.
itemOrders
+-------+---------+--------+
| id | orderid | itemid |
+-------+---------+--------+
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 2 | 2 |
| 5 | 3 | 1 |
| 6 | 3 | 2 |
+-------+---------+--------+
And
itemDelivered
+-------+-------------+--------+
| id | orderId | itemid |
+-------+-------------+--------+
| 1 | 2 | 2 |
| 2 | 3 | 2 |
| 3 | 2 | 1 |
+-------+-------------+--------+
From the above scenario I want all those distinct items whose max orderId in the table itemDelivered is less than max orderId in the table itemOrders.
In the above example I should get itemid 1 as the result, as it's max orderid is 2 in table itemDelivered, which is less than its max orderid in table itemOrders which is 3.
I wrote the following query but it gives me both the items, 1 and 2 as item No. 2 doesn't have orderId 1 in itemDelivered table.
SELECT DISTINCT( itemid )
FROM itemorders
WHERE orderid NOT IN (SELECT orderid
FROM itemdelivered)
You can LEFT JOIN between the two table using itemid, and GROUP BY on the itemid.
Eventually use HAVING clause to consider only those itemid values, where MAX(itemdelivered.orderid) < MAX(itemorders.orderid)
View on DB Fiddle
SELECT io.itemid
FROM itemorders AS io
LEFT JOIN itemdelivered AS id
ON id.itemid = io.itemid
GROUP BY io.itemid
HAVING MAX(id.orderid) < MAX(io.orderid)
OR MAX(id.orderid) IS NULL
Result
| itemid |
| ------ |
| 1 |
Ok, manage to write a query which gives the desired output.
SELECT io.itemid
FROM itemorders as io
LEFT JOIN itemdelivered AS id ON io.orderid = id.orderid AND io.itemid = id.itemid
WHERE id.itemid IS NULL
HAVING MAX(id.orderid) IS NULL
ORDER BY io.id

MySQL How to Select smth by MAX(id)....WHERE userID = some number GROUP BY smth

I have next table in my DB:
personal_prizes
___________ ___________ _________ __________
| id | userId | specId| grp |
|___________|___________|_________|__________|
| 1 | 1 | 1 | 1 |
| 2 | 1 | 2 | 1 |
| 3 | 2 | 3 | 1 |
| 4 | 2 | 4 | 2 |
| 5 | 1 | 5 | 2 |
| 6 | 1 | 6 | 2 |
| 7 | 2 | 7 | 3 |
| 8 | 1 | 13 | 4 |
|___________|___________|_________|__________|
I need to select specId by max id group by grp.
So I have composed next query
SELECT pp.specId
FROM personal_prizes pp
WHERE pp.specId IN (SELECT MAX(pp1.id)
FROM personal_prizes pp1
WHERE pp1.userId = 1
GROUP BY pp1.grp)
And it's work for my little table. But when I try to implement it for my prod db with personal_prizes > 100,000.
Please help me optimize it
The query you have should work fine. Make sure though that you not only have an index on id (which I suppose is the primary key), but also one on specId.
Just as an alternative, you might try this one:
select group_concat(pp.specId order by pp1.id desc)+0 as result_specId
from personal_prizes pp1
left join personal_prizes pp on pp.specId = pp1.id
where pp1.userId = 1
group by pp1.grp
having result_specId is not null;
The idea here is that the sub query is promoted to the main query, and the specId is retrieved by an outer join. The group_concat aggregation function will list the one of interest as the first. The having clause will exclude the cases where no matching specId was found.
Note that this will only give the same results if the specId field is guaranteed to be non-null.

Extend Mysql table for same id

My table structure is:
id | type | attribute | customer_id | value
1 | 2 | 1 | 1 | some
2 | 2 | 2 | 1 | this
3 | 2 | 3 | 1 | that
4 | 2 | 1 | 2 | cool
5 | 2 | 2 | 2 | just
etc
I want to add value='mine' as attribute 4 to each customer_id.
INSERT INTO mytable
SET type='2', attribute='4, value='mine'
The question is how to bind it on customer_id and only once per customer?
INSERT INTO myTable(type, attribute, customer_id, value)
SELECT 2 type,
4 attribute,
s.customer_id,
'mine' `value`
FROM (SELECT DISTINCT customer_id FROM myTable) s

Mysql select row based on multiple rows in same table

I have the following table structure:
item_id | value |
==================
1 | 1 |
1 | 3 |
1 | 4 |
2 | 2 |
2 | 3 |
2 | 4 |
2 | 5 |
3 | 1 |
3 | 5 |
3 | 6 |
4 | 1 |
4 | 3 |
4 | 4 |
4 | 5 |
I have a query that returns those item_id whose value matches with 1, 3 and 4.
So here, the item_ids that should be returned are 1 and 4.
My query:
select item_id from table t
where exists (select item_id from table t1 where value = 1 and t1.item_id = t.item_id)
and exists (select item_id from table t1 where value = 2 and t1.item_id = t.item_id) group by item_id
This query is working fine. Here i am matching only 3 values. What if i want to match 50 such values from the table? (all the 50 values are stored in a php array) The query will be huge and also i want to do the same thing from two different tables in the same query. So, this will double the size of an already huge query. Please suggest me some other way around.
Edited::
table 2
--------
item_id | user_id |
==================
1 | 1 |
1 | 5 |
1 | 7 |
2 | 2 |
2 | 3 |
2 | 4 |
2 | 5 |
3 | 1 |
3 | 5 |
3 | 6 |
4 | 1 |
4 | 3 |
4 | 4 |
4 | 5 |
Now, i want item_id where values from table1 are 1,3,4 and user_id from table2 are 1,5,7
This problem is called Relational Division.
SELECT item_ID
FROM tableName
WHERE value IN (1,3,4)
GROUP BY item_ID
HAVING COUNT(*) = 3
if uniqueness was not enforce on column value for every item_id, DISTINCT is required to count only unique values,
SELECT item_ID
FROM tableName
WHERE value IN (1,3,4)
GROUP BY item_ID
HAVING COUNT(DISTINCT value) = 3
SQLFiddle Demo (both query included)
SQL of Relational Division

SQL Group by using the First N elements in each group [duplicate]

This question already has an answer here:
Top N per Group Sql problem in mysql
(1 answer)
Closed 9 years ago.
Suppose I have the next table:
+------------+---------+
| MovieId | rating |
+------------+---------+
| 1 | 4 |
| 1 | 3 |
| 1 | 2 |
| 1 | 4 |
| 1 | 5 |
| 2 | 3 |
| 2 | 4 |
| 2 | 2 |
| 3 | 1 |
| 3 | 2 |
| 3 | 3 |
| 3 | 5 |
| 4 | 4 |
| 4 | 2 |
+------------+---------+
I would like to get the average by group BUT using the first 2 elements on each group.
Example:
+------------+---------+
| MovieId | rating |
+------------+---------+
| 1 | 4 |
| 1 | 3 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 4 | 4 |
| 4 | 2 |
+------------+---------+
answer expected:
+------------+---------+
| MovieId | AVG |
+------------+---------+
| 1 | 3.5 |
| 2 | 3.5 |
| 3 | 1.5 |
| 4 | 3 |
+------------+---------+
This is the SQL query I have to get the AVG for all of the movies. But as I said, I would like to use just the first 2 elements for each group.
SELECT movieid, AVG(cast(rating as DECIMAL(10,2))) AS AVG
FROM ratings
group by movieid
If you can help me to make the SQL I appreciate. I will also use Linq just in case some of you know it.
In a SQL DBMS -- as in the relational model -- there is no "first". Do you mean any arbitrary 2 rows for each movie, or the two highest ratings, or something else?
If you can't define an order, then the query is meaningless.
If you can define an order, join the table to itself as I show in my canonical example to create a ranking, and select where RANK < 3.
FOR Mysql:-
select id, avg(rating)
from (SELECT a.*, #num := #num + 1 rownum,
(select count(*)
from movies m
where m.id<=a.id) last_count,
(select count(*)
from movies m1
where a.id=m1.id) grp_count
from movies a, (SELECT #num := 0) d) f
where grp_count-(last_count-rownum)<=2
group by id;
you can use rownum function in oracle. And row_number() function in sql server.
This is a solution in SQL
Create table #tempMovie (movieId int ,rating int)
INSERT INTO #tempMovie
Select * from table where movieidid=1 Limit 2
Union all
Select * from table where movieidid=2 Limit 2
Union all
Select * from table where movieidid=3 Limit 2
Union all
Select * from table where movieidid=4 Limit 2
Temporary table #tempmovie table will contain data like this
+------------+---------+
| MovieId | rating |
+------------+---------+
| 1 | 4 |
| 1 | 3 |
| 2 | 3 |
| 2 | 4 |
| 3 | 1 |
| 3 | 2 |
| 4 | 4 |
| 4 | 2 |
+------------+---------+
then apply group by
Select movieId, AVG(rating)
from #tempMovie
Group by movieId
Drop table #tempmovie