Case in list - Tableau - mysql

I'm trying to filter out a huge amount of data out so i decided to create a calculated field and using case if product_id in the list then '1' else '0'
but for some reason it though syntax error.
this is my calculated field:
CASE when product_id in (
'31049','31048','26166','27816','26031','28861','28864','28863','28203','28110','20641','38112','45174','20645','28404','20646','20648','26159','33287','31417','40551','41020','40550','40550','40553','40554','29804','29941','31430','33354','36730','26073','31432','31433','31431','38154','38166','26029','28341','45138','38069','42069','26060','26060','33886','33886','28392','29518','44879','20651','20655','42914','37535','28031','27588','29297','37688','37709','29551','29551','30183','29550','26187','29549','41348') THEN '1' ELSE '0'
END
Any idea who it should be written?
Thanx in advance :)

On a sample dataset this works:
SELECT RIDE_ID as ri,
CASE
WHEN ri in ('5EB0FAD625CFAEAB', '5A9314E3AF8DCC30') THEN '1'
ELSE '0'
END AS result
FROM CITIBIKE_TRIPS LIMIT 10;
I get:

yes it works in the database but not in Tableau :) I couldn't run it in a calculated field
Maybe using LATERAL would allow to run it from Tableau:
CREATE OR REPLACE TABLE t(ID INT, product_id TEXT);
INSERT INTO t VALUES (1, '31049'),(2,'31048'), (3, '100');
SELECT *
FROM t
,LATERAL (SELECT CASE WHEN t.product_id IN ( '31049','31048','26166','27816'/*...*/)
THEN '1' ELSE '0' END) AS s(result);

One option— create a table with your keys that you wish to filter, and then use a join to let the database do the work. Could be easier to maintain. Likely more efficient
Another option is to create a set in Tableau based on the product_id field. Define that set by checking the product ids you wish, and then place the set of the filter shelf to filter to either include or exclude the product_ids in your set.

Related

Set a column value to be null based on value from another column

I'm preparing a select query that should set a field as null if certain value is present in another field of the same query.
select statement_id, prod_id, description, exp_type,
curr_amt as Digital_income, curr_amt as Physical income
from table1
where date(created) = 'somedate'
Here, the field exp_type will have values like "Digital", "Physical", "Download", "Stream".
I'm cloning curr_amt field as digital and physical. Most of the times both will have similar values only.
My requirement is if the exp_type is "Physical" I need the curr_amt as 'Digital_income'` to be null and visa versa.
Can anyone assist me in getting the desired output?
I tried using CASE, ISNULL and COALESCE but in vain
Use IF().
select statement_id, prod_id, description, exp_type,
IF(exp_type = 'Digital', curr_amt, NULL) as Digital_income,
IF(exp_type = 'Physical', curr_amt, NULL) as Physical_income
from table1
where date(created) = 'somedate'
DEMO

Select id from input list NOT present in database

With MySql vers 8.0:
CREATE TABLE cnacs(cid VARCHAR(20), PRIMARY KEY(cid));
Then,
INSERT INTO cnacs VALUES('1');
The first two statements execute successfully. The next statement does not, however. My goal is to return a list of unused cid's from the input table [1, 2]:
SELECT * FROM (VALUES ('1'),('2')) as T(cid) EXCEPT SELECT cid FROM cnacs;
In theory, I'd like the output to be '2', since it has not yet been added. The aforementioned query was inspired by Remus's answer on https://dba.stackexchange.com/questions/37627/identifying-which-values-do-not-match-a-table-row
This is at least the correct syntax for what you are trying to do.
If this query is anything more than a learning exercise though I'd rethink the approach, storing these '1' and '2' values (or however many there ends up being) in their own table
SELECT Column_0
FROM (SELECT * FROM (VALUES ROW('1'), ROW('2')) TMP) VALS
LEFT
JOIN cnacs
ON VALS.Column_0 = cnacs.cid
WHERE cnacs.cid IS NULL

SQL INSERT INTO xxx WHERE NOT EXIST

I am trying to insert into a table, but only if unique. I can do this on one criteria, but not two? I am not sure where I am going wrong? It doesn't return an error, just behaves as if there is only one criteria.
Simple table, autoID, status, type
INSERT INTO alarms (status, type)
SELECT * FROM (SELECT '2', '1') AS tmp
WHERE NOT EXISTS
( SELECT type FROM alarms WHERE (type = '1')) LIMIT 1;
This works fine, it will only insert if there are no other entries with a type of 1.
I would like to have multiple criteria, ie if already in the table type=1 AND status=5 then insert a new entry of type=1 and status=2. I have tried the following (with a few variations) but cannot get it to work. No errors, just behaves as if there is only one criteria.
INSERT INTO alarms (status, type)
SELECT * FROM (SELECT '2', '1') AS tmp
WHERE NOT EXISTS
( SELECT type, status FROM alarms WHERE (type = '1' AND status = '5')) LIMIT 1;
Any advice? Or do I need to do a separate call to determine the multiple criteria existence.
Thanks.
Have you tries using if-begin-end instead?
The code might be simpler but, this still count as a single statement I suppose.
If Not Exists( SELECT type, status FROM alarms WHERE (type = '1' AND status = '5'))
Begin
INSERT INTO alarms (status, type) values ("Y","type")
End
Try using "HAVING"
INSERT INTO alarms (status, type)
SELECT status, type
FROM alarms_duplicated AS a
WHERE status = '2' AND type = '1'
GROUP BY status, type
HAVING COUNT(*) = 1
thanks for your input.
I would look as if the IF NOT EXIST.... WHERE will not work, apparently the WHERE statement is not compatible with mySQL. So I did it a different way!
(Entirely different approach to the issue at hand, not relative to this discussion).

MYSQL - COUNT() NULL Values

This has been racking my head. I've scoured the internet (including this place) and can't find a solution. So as a last resort I was hoping the good people of this forum might be able to help me out.
I have two tables:
TableA
Order_detailsID
OrderID
TitleID
Return_date
TableB
TitleID
Title_name
Quantity_in_stock
And would like to run a query that shows the remaining 'Quantity_in_stock'.
If the 'Return_date' is set to NULL then it means the item is currently out -- so I have been trying to use the count() function for the NULL values and subtract it from the 'Quantity_in_stock'.
This is the script I have so far:
DELIMITER //
CREATE PROCEDURE InStock()
BEGIN
Select TableB.TitleID,
TableB.Title_name,
TableB.Quantity_in_stock AS 'Total_Stock',
COUNT(TableA.return_date IS NULL) AS 'Rented_Out',
TableB.Quantity_in_stock - COUNT(TableA.return_date IS NULL) AS 'Remaining Stock'
From TableB
LEFT JOIN TableA
ON TableA.TitleID = TableB.TitleID
GROUP BY TableB.TitleID;
END//
This works if there is one of more of the TitleIDs at NULL, however if there are no values at NULL, then the Count() is still returning a value of 1 when it should be 0.
What am I doing wrong?
Instead of:
COUNT(TableA.return_date IS NULL)
use this:
SUM(CASE
WHEN TableA.TitleID IS NULL THEN 0
WHEN TableA.return_date IS NOT NULL THEN 0
ELSE 1
END)
The problem with the TableA.return_date IS NULL predicate is that it's true in two completely different situations:
When there is no matching record in TableA
When there is a matching record but TableA.return_date value of this exact record is NULL.
Using the CASE expression you can differentiate between these two cases.
I will like to mention a simple concept here, just keep counting the rows when that particular column is null.
select count(*) from table_name where column_name is null

MySQL - tell if column _all_ has same value

I'm trying to write a query like
if (select count(*) from Users where fkId=5000 and status='r') =
(select count(*) from Users where fkId=5000) then ..
in just one query.
What this means is, if all the rows that have fkId=5000 also have status=r, then do something.
There can be any number of rows with fkId=5000, and any fraction of those rows could have status=r, status=k, status=l, status=a etc. I'm interested in the case where ALL the rows that have fkId=5000 also have status=r (and not any other status).
The way I'm doing it now is
how many rows with id=5000 and status = 'r'?
how many rows with id=5000?
are those numbers equal? then ..
I'm trying to figure out how to rewrite this query using only 1 query, instead of 2. Keyword ALL didn't seem to be able to write such a query (<> ALL is equivalent to NOT IN). I tried a couple of GROUP BY formulations but could not get the correct result to appear.
The most efficient way to do this is:
if not exists (select 1
from users
where fkid = 5000 and (status <> 'r' or status is null)
)
This will stop the query at the first non-matching row.
I suggest you to check for any rows with status not equal to 'r'
SELECT count(*)>0 FROM Users WHERE fkId = 5000 AND status != 'r'
In the following case, if the number 1 is "true" (which it is) then you'll get Yes back, and if not you'll get No back:
SELECT IF(1, 'Yes', 'No') AS yesorno
(Go ahead -- try it!)
In your case however, the following would be more appropriate:
SELECT IF (
(SELECT COUNT(*) FROM Users WHERE fkId=5000 AND status IN('r') AND status NOT IN('1', 'a', 'k')) = (SELECT COUNT(*) FROM Users WHERE fkId=5000),
'They are equal.',
'They are not equal.'
)
AS are_they_equal
By adding AS, you can manipulate the name of the "column" that's returned to you.
Hope that helps... Also, see this page if you'd like more info.
:)
EASY!
Simply join back to the same table. Here is the complete code for testing:
CREATE TABLE Users(id int NOT NULL AUTO_INCREMENT, fkID int NOT NULL, status char(1), PRIMARY KEY (id));
INSERT Users (fkID, status) VALUES (5000, 'r');
INSERT Users (fkID, status) VALUES (5000, 'r');
INSERT Users (fkID, status) VALUES (5000, 'r');
-- The next query produces "0" to indicate no miss-matches
SELECT COUNT(*) FROM Users u1 LEFT JOIN Users u2 ON u1.id=u2.id AND u2.status='r' WHERE u1.fkID=5000 AND u2.id IS NULL;
-- now change one record to create a miss-match
UPDATE Users SET status='l' WHERE id=3 ;
-- The next query produces "1" to indicate 1 miss-match
SELECT COUNT(*) FROM Users u1 LEFT JOIN Users u2 ON u1.id=u2.id AND u2.status='r' WHERE u1.fkID=5000 AND u2.id IS NULL;
DROP TABLE Users;
So all you need to test for in the result is that it's 0 (zero) meaning everything has fkID=5000 also has status='r'
If you properly index your table then joining back to the same table is not an issue and certainly beats having to do a 2nd query.
Besides the NOT EXISTS version - which should be the most efficient as it does no counting at all and exits as soon as it finds a value that doesn't match the conditions, there is one more way, that will work if status is not nullable and will be efficient if there is an index on (fkId, status):
IF EXISTS
( SELECT 1
FROM Users
WHERE fkId = 5000
HAVING MIN(status) = 'r'
AND MAX(status) = 'r'
)
There is one difference though. The above will show false if there are no rows at all with fkId=5000, while the NOT EXISTS version will show true - which is probably what you want anyway.