I am having trouble with a mysql query. I want to exclude values of 2. So I thought I would do following:
table products
id | name | backorder
-------------------
1 | product1 | NULL
2 | product2 | NULL
3 | product3 | 2
SELECT name from `products` p
WHERE backorder <> '2'
However, This is not giving the desired result of product1, product 2 It is giving an empty results table.
On the other hand if I use
SELECT name from `products` p
WHERE backorder = '2'
Then it produces: product3. But I want to get those records where it is not equal to 2.
Something is not working with the <> '2'. Could it be that the NULL values are throwing it off? Can anyone suggest a fix.
Thanks in advance!
use IS NULL or IS NOT NULL to compare NULL values because they are simply unknown.
SELECT name
from products p
WHERE backorder IS NULL OR backorder <> 2
SQLFiddle Demo
SQLFiddle Demo (added some records)
Working with NULL Values
Use the <=> operator.
You can use:
SELECT `name` FROM `products` `p`
WHERE NOT `backorder` <=> '2'
or
SELECT `name` FROM `products` `p`
WHERE !(`backorder` <=> '2')
See this answer for more information about the <=> operator:
What is this operator <=> in MySQL?
Sorry to open this
We can use this also
SELECT name
from products p
WHERE COALESCE(backorder,1) <> 2
Try this and see.
SELECT name from `products` p
WHERE backorder != '2'
Related
I need to get all rows that are in the table A, but joining with the table B (basically a LEFT JOIN), but also, I need to get the A table row itself, for example, with these tables:
Table A:
id
name
1
Random name
2
Random name #2
Table B:
id
parent_id
location
1
2
Location #1
2
2
Location #2
With this query:
SELECT * FROM A
LEFT JOIN B
ON A.id = B.parent_id;
I get something like this:
id
name
id
parent_id
location
1
Random name
NULL
NULL
NULL
2
Random name #2
1
2
Location #1
2
Random name #2
2
2
Location #2
But I want to get something like this:
id
name
id
parent_id
location
1
Random name
NULL
NULL
NULL
2
Random name #2
NULL
NULL
NULL
2
Random name #2
1
2
Location #1
2
Random name #2
2
2
Location #2
As you can see, there is a row by itself of "Random name #2" separated from its joins, how can I do that?
The main idea is that there are an ads table (the table A), but also, there are a subads table (the table B) with little variations of the ads table, and I need to show all ads and subads in a unique query.
Tanks a lot!
Two suggestions:
SELECT * FROM A
INNER JOIN B
ON A.id = B.parent_id
UNION ALL
SELECT *, NULL, NULL, NULL FROM A
or
SELECT A.*,B.*
FROM (SELECT 1 A_ONLY UNION ALL SELECT 0) A_ONLY
CROSS JOIN A
LEFT JOIN B
ON A.id = B.parent_id AND NOT A_ONLY
WHERE A_ONLY OR B.parent_id
The latter is an approach you can use to emulate WITH ROLLUP when that isn't allowed or when you want something slightly different than that produces (here, avoiding a grand total record and avoiding a double record when there are no B rows).
Probably not the best implementation, but until someone comes up with a proper solution...
SELECT A.id, name, B.id, parent_id, location FROM A
LEFT JOIN B
ON A.id = B.parent_id;
UNION ALL
SELECT A.id, name, NULL as id, NULL as parent_id, NULL as location FROM A
WHERE A.id IN (SELECT parent_id FROM B)
Simply UNION ALL with another query taking the values from A that had matches on B, hence no NULL values from the first query.
you need only the NULL added rows from A and the rest of the inner JOIN
CREATE TABLE A
(`id` int, `name` varchar(14))
;
INSERT INTO A
(`id`, `name`)
VALUES
(1, 'Random name'),
(2, 'Random name #2')
;
CREATE TABLE B
(`id` int, `parent_id` int, `location` varchar(11))
;
INSERT INTO B
(`id`, `parent_id`, `location`)
VALUES
(1, 2, 'Location #1'),
(2, 2, 'Location #2')
;
(SELECT A.id as a_id,A.name,B.* FROM A
INNER JOIN B
ON A.id = B.parent_id)
UNION
(SELECT A.*,NULL,NULL,NULL FROM A)
ORDER by a_id,id;
a_id | name | id | parent_id | location
---: | :------------- | ---: | --------: | :----------
1 | Random name | null | null | null
2 | Random name #2 | null | null | null
2 | Random name #2 | 1 | 2 | Location #1
2 | Random name #2 | 2 | 2 | Location #2
db<>fiddle here
You can make INNER JOIN instead of LEFT JOIN and UNION ALL with table A content:
Both queries must return the same number of columns.
SELECT *, NULL, NULL, NULL
FROM A
UNION ALL
SELECT *
FROM A
INNER JOIN B ON A.id = B.parent_id;
I need to get the id_user by values given in other columns. My table look like this:
id(AI,PK) id_user attr_name attr_value
----------------------------------------------------
1 1 hair brown
2 1 eyes green
3 2 hair blond
4 1 age 40
5 1 sex male
6 2 eyes green
7 2 age 40
8 2 sex male
When I try a query like this:
select distinct id_user where (attr_name='hair' and attr_value='blond') or (attr_name='eyes' and attr_value='green')
I will obviously get id_user=1 and 2, because both of them have green eyes.
If I change "or" to "and" it seems that the query does not work at all. But I need "and" because 2 (or even more, I shortened my example) conditions must be met, to get the specified id_user:
select distinct id_user where (attr_name='hair' and attr_value='blond') and (attr_name='eyes' and attr_value='green')
How to "pair" those 2 brackets, so I will get only a user where both conditions met: green eyes and blond hair?
Use post aggregate filtering with HAVING.
WHERE filters rows, HAVING with aggregate functions filters groups.
SELECT id_user FROM t
GROUP BY id_user
HAVING SUM(attr_name='hair')>0 AND SUM( attr_value='blond') >0
AND SUM(attr_name='eyes')>0 AND SUM( attr_value='green') >0
Another approach is.
SELECT `u1`.`id_user`,
IF(`u1`.`attr_name` RLIKE 'hair' AND `u1`.`attr_value` = 'blond',1,0) AS `blond`,
IF(`u2`.`attr_name` RLIKE 'eyes' AND `u2`.`attr_value` = 'green',1,0) AS `green`
FROM `users` `u1`
INNER JOIN `users` `u2`
ON `u1`.`id_user`=`u2`.`id_user`
HAVING `green`+`blond` = 2;
OR
SELECT `u1`.`id_user`
FROM `users` `u1`
INNER JOIN `users` `u2`
ON `u1`.`id_user`=`u2`.`id_user`
WHERE IF(`u1`.`attr_name` RLIKE 'hair' AND `u1`.`attr_value` = 'blond',1,0) + IF(`u2`.`attr_name` RLIKE 'eyes' AND `u2`.`attr_value` = 'green',1,0) = 2;
The result is
id_user blond green
2 1 1
To re-create the example use:
create table `users` (
`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
`id_user` INT,
`attr_name` VARCHAR(255) NOT NULL,
`attr_value` VARCHAR(255) NOT NULL
) ENGINE=INNODB;
INSERT INTO `users` (`id`,`id_user`,`attr_name`,`attr_value`) VALUES (1,1,'hair','blond'),(2,1,'eyes','blue'),(3,2,'hair','blond'),(4,2,'eyes','green'),(5,2,'sex','male'),(6,2,'age','42'),(7,1,'sex','female'),(8,1,'age','39');
Try it on SQL Fiddle
I have a data file that looks like this
item_id | status
1 | null
2 | null
2 | new
3 | new
4 | null
4 | new
5 | null
Notice that item 2 and 4 have both 2 status: null and new.
I want to create a query that would extract only item_id with 1 status, which is null. So, i want my query to extract only 1 and 5.
I ended up doing this, but this doesn't look efficient:
1.List items with null status
create table query_1 as
select * from table1 where status = 'null';
2.List item with new status
create table query_2 as
select * from table1 where status = 'new';
3.select all results from query 1, excluding any id found from the results of query 2
select * from query_1 where item_id not in (select item_id from query_2)
Am I over thinking this? Is there a simpler query that can accomplish this?
First you have to check for null values with IS NULL. =null or ='null' won't work.
SELECT item_id, MAX(status)
FROM table1
GROUP BY item_id
HAVING MAX(status) IS NULL
select item_id
from table1
group by item_id
having count(*) = 1 and status is null
You can use self-join. What you need to do is remove the item_id's having new values. The remaining entries would be would you want. So you can frame your query as such :
SELECT item_id,
status
FROM tableName
WHERE item_id NOT IN (SELECT item_id
FROM #tab
WHERE status = 'new')
You can see this here -> SQL Fiddle Example
SELECT item_id FROM items
WHERE status IS NOT NULL
AND item_id NOT IN
(SELECT item_id FROM items
WHERE status IS NULL
)
You could use DISTINCT in this instance
SELECT DISTINCT item_id FROM items WHERE status IS NULL;
I have this table named prizes with the following structure
`id` (PRIMARY)
`id_multiple`
`desc`
`winner`
I want to select those who don't have a winner (NULL) and display them together if they have the same id_multiple showing the count of how many left to win of that id_multiple.
So for example, there's this values:
id_multiple | winner | desc
1 | NULL | voucher
1 | jonh | voucher
2 | NULL | car
2 | NULL | car
And I want to display:
Left to win:
1 Voucher
2 Car
(The desc will be the same for all id_multiple so it might be ambiguous to use id_multiple?)
Something like:
SELECT id_multiple,count(id_multiple),`desc`
FROM `yourtable`
WHERE `winner` IS NULL
GROUP BY `id_multiple`
You could count a case expression:
SELECT id_multiple, COUNT(CASE WHEN winner IS NULL THEN 1 END) AS left_to_win, `desc`
FROM mytable
GROUP BY id_multiple, `desc`
Or, even simpler, with a sum expression that takes advantage of the fact that true is interpreted as 1 and false as 0 in numerical contexts:
SELECT id_multiple, SUM(winner IS NULL) AS left_to_win, `desc`
FROM mytable
GROUP BY id_multiple, `desc`
I am trying to get a list of values from the same column in a table by running two queries.
This is what the table looks like:
******************************************
Key | Short_text | UID | Boolean_value
******************************************
Name | John | 23 | null
******************************************
Male | NULL | 23 | true
******************************************
Name | Ben | 45 | null
******************************************
Male | NULL | 45 | true
I am trying to get the SHORT_TEXT of the NAME rows if the Boolean values of the Male rows are true based on the UIDs
This is what I have so far (Which is throwing an error: Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
)
SELECT SHORT_TEXT_VALUE
FROM Table
WHERE ((SELECT UID
FROM Table
WHERE KEY = 'NAME') =
(SELECT CUSTOMER_UID
FROM Table
WHERE KEY = 'Male'
AND BOOLEAN_VALUE = 1))
I am very new to sql so I am not sure what I should do to achieve what I would like.
Any help would greatly be appreciated.
You can join your table with itself:
SELECT
t1.UID,
t1.Short_text
FROM
tablename t1 INNER JOIN tablename t2
ON t1.UID=t2.UID
WHERE
t1.Key='Name' AND t2.Key='Male' AND t2.Boolean_value=TRUE
or this with EXISTS:
SELECT
t1.UID,
t1.Short_text
FROM
tablename t1
WHERE
t1.Key='Name' AND
EXISTS (SELECT * FROM tablename t2
WHERE t1.UID=t2.UID AND t2.Key='Male' AND t2.Boolean_value=1)
I am unsure what you are trying to accomplish but basing on your code I think this is what you want
SELECT SHORT_TEXT_VALUE
FROM Table
WHERE KEY='Name'
and UID in(SELECT UID
FROM Table
WHERE KEY = 'Male'
AND BOOLEAN_VALUE = 1)
But on a more important note. You might want to think about your redesigning your table design. Why is Male details of a specific uid on a different row?
Hi try it with a subquery, try this:
SELECT Short_text
FROM table
WHERE uid in (SELECT uid FROM table WHERE boolean_value = "true")
AND Short_text IS NOT NULL
Make sure that the values of the Male rows are(NULL) and not the string with "NULL"
Btw. This table does not match to the normalization-form of database-tables. Please read the introduction to database normalization