Getting data if one value is NULL - mysql

I am having an issue with the code below and my issue is the following:
I need to be able to select the shop_shipping_rule_region_code if the country_iso is NULL but I also need to get the $country_iso data as well if present
What I am after:
The Final Result will have:
Overnight UPS
NZ Snail Mail
Whole World (in this example)
DB:
`shop_shipping_rules` (`shop_shipping_rule_id`, `shop_shipping_rule_country_iso`, `shop_shipping_rule_region_code`, `shop_shipping_rule_name`,
`shop_shipping_rule_type_single`, `shop_shipping_rule_item_single`, `shop_shipping_rule_type_multi`,
`shop_shipping_rule_item_multiple`,`shop_shipping_rule_created`, `shop_shipping_rule_modified`, `website_id`)
VALUES
(41, 'NZ', 'ALL', 'Overnight UPS', 'single', 2.00, 'multi', 4.00, '2013-11-05 02:30:19', '2013-11-05 03:00:27', 64),
(44, 'NZ', NULL, 'NZ Snail Mail', 'single', 25.00, 'multi', 35.00, '2013-11-14 03:57:06', NULL, 64),
(45, NULL, 'ALL', 'Whole World', 'single', 90.00, 'multi', 150.00, '2013-11-14 05:05:53', NULL, 64),
(46, NULL, 'EU', 'EU Ship', 'single', 28.00, 'multi', 35.00, '2013-11-15 01:04:01', NULL, 64);

if (isset($country_iso))
$sql = "SELECT * FROM shop_shipping_rules WHERE country_iso IS NULL OR country_iso = '$country_iso' ";
else
$sql = "SELECT * FROM shop_shipping_rules WHERE country_iso IS NULL";

Related

i'm having issues with code syntax e.g. : null is not valid at this position, expecting ')'

i am very new to SQL and have to complete my first ever project. i keep getting errors to do with syntax and i have no idea where i've gone wrong, i've checked for commas, hyphens in the wrong place and feel like i'm going mad. can someone help me please?
the errors:
1. (49, 'Purple Kiss', null, '퍼플키스', '2021-03-15', 'RBW', 7, 7, 'PLORY', true), "null" is not valid at this position, expecting ')'
(again, where is the null coming from?)
2. (37, 'Uni.T', null, '유니티', '2018-05-18', 'Unit Culture', 8, 9, false), extraneous input false found, expecting ')'
(what is an extraneous input?)
3. (26, 'The Ark', null, '디아크', '2015-04-12', 'Music K', 5, 5, null, false),
9 is not valid at this position, expecting ')'
(not sure where the 9 is coming from)
it might be a really simple fix, but again, this is my first project and have no idea what's wrong, please help! i don't know if it's something to do with the korean characters? i read somewhere to use 'NVARCHAR' as the datatype so that's what i used, please explain it to me like i'm a child xD
create database female_kpop_idols;
use female_kpop_idols;
create table kpop_girlgroups
(idol_id int primary key auto_increment not null,
eng_name varchar(50) not null,
short_name varchar(50),
kor_name nvarchar(50) not null,
debut date not null,
company varchar(50) not null,
members int not null,
orig_members int not null,
fanclub varchar(50),
active boolean);
insert into kpop_girlgroups
values
(1, 'Baby V.O.X', null, '베이비복스', '1997-07-05', 'DR Music', 5, 5, null, false),
(2, 'S.E.S', null, '에스.이.에스', '1997-11-01', 'SM', 3, 3, null, false),
(3, 'Fin.K.L', null, '핑클', '1998-05-22', 'DSP', 4, 4, null,
(4, 'Brown Eyed Girls', 'B.E.G', '브라운 아이드 걸스 ', '2006-03-02', 'Mystic', 4, 4, 'Everlasting', true),
(5, 'Wonder Girls', 'WG', '원더걸스', '2007-02-13', 'JYP', 4, 5, 'Wonderful', false),
(6, 'Kara', null, '카라', '2007-03-29', 'DSP', 4, 5, 'Kamilia', false),
(7, 'Girls\' Generation', 'SNSD', '2007-08-05', 'SM', 5, 9, 'SONE', true),
(8, 'After School', null, '애프터스쿨', '2009-01-15', 'Pledis', 6, 5, 'Playgirlz', false),
(9, '2NE1', null, '투애니원', '2009-05-06', 'YG', 3, 4, 'Blackjack', false),
(10, '4Minute', null, '포미닛', '2009-06-15', 'Cube', 5, 5, '4nia', false),
(11, 'T-ara', null, '티아라', '2009-07-29', 'MBK', 4, 6, 'Queen\'s', true), -- hiatus --
(12, 'f(x)', null, '에프엑스', '2009-08-24', 'SM', 4, 5, 'MeU', false),
(13, 'Sistar', null, '씨스타', '2010-03-06', 'Starship', 4, 4, 'STAR1', false),
(14, 'missA', null, '미쓰에이', '2010-07-01', 'JYP', 3, 4, 'Say A', false),
(15, 'Girl\'s Day', 'GsD', '걸스데이', '2010-07-09', 'DreamT', 4, 5, 'Dai5y', true), -- hiatus --
(16, 'Rania', null, '라니아', '2011-04-06', 'DR Music', 5, 8, null, false), -- redebuted as Black Swan --
(17, 'Brave Girls', null, '브레이브걸스', '2011-04-08', 'Brave', 4, 5, null, true),
(18, 'Apink', null, '에이핑크', '2011-04-19', 'Plan A', 6, 7, 'Pink Panda', true),
(19, 'EXID', null, '이엑스아이디', '2012-02-16', 'Yedang', 5, 6, 'LEGO', true),
(20, 'AOA', null, '에이오에이', '2012-07-30', 'FNC', 4, 8, 'ELVIS', true), -- hiatus --
(21, 'Mamamoo', null, '마마무', '2014-06-18', 'RBW', 4, 4, 'Moomoo', true),
(22, 'Red Velevet', 'RV', '레드벨벳', '2014-08-01', 'SM', 5, 4, true),
(23, 'Minx', null, '밍스', '2014-09-18', 'Happy Face', 5, 5, false), -- redebuted as DreamCatcher --
(24, 'Gfriend', null, '여자친구', '2015-01-15', 'Source', 6, 6, 'Buddy', false),
(25, 'CLC', null, '씨엘씨', '2015-03-19', 'Cube', 7, 5, 'Cheshire', false),
(26, 'The Ark', null, '디아크', '2015-04-12', 'Music K', 5, 5, null, false), -- some members redebuted as KHAN --
(27, 'Oh My Girl', 'OHMG', '오마이걸', '2015-04-21', 'WM', 6, 8, 'Miracle', true),
(28, 'TWICE', null, '트와이스', '2015-10-20', 'JYP', '9, '9, 'ONCE', true),
(29, 'WJSN', 'Cosmic Girls', '2016-02-25', 'Starship', 13, 12, 'Ujung', true),
(30, 'IOI', 'I.O.I', '아이오아이', '2016-05-04', 'YMC', 11, 11, null, false),
(31, 'BLACKPINK', null, '블랙핑크', '2016-08-08', 'YG', 4, 4, 'BLINK', true),
(32, 'Momoland', null, '모모랜드', '2016-11-09', 'Duble Kick', 9, 6, true),
(33, 'DreamCatcher', null, '드림캐쳐', '2017-01-13', 'Happy Face', 7, 7, 'InSomnia', true),
(34, 'Pristin', null, '프리스틴', '2017-03-21', 'Pledis', 10, 10, 'HIgh', false), -- some redebuted as Hinapia --
(35, 'fromis_9', null, '프로미스나인', '2018-01-24', 'Pledis', 9, 9, 'Flover', true),
(36, '(G)I-DLE', null, '(여자)아이들', '2018-05-02', 'Cube', 5, 6, 'Neverland', true),
(37, 'Uni.T', null, '유니티', '2018-05-18', 'Unit Culture', 8, 9, false), -- come back to this one and add Sonamoo, SPICA, DIA, April, Dal Shabet, Laboum, The ARK --
(38, 'KHAN', null, '칸', '2018-05-23', 'Maroo', 2, 2, false),
(39, 'Loona', 'LOOΠΔ', '이달의 소녀', '2018-08-20', 'Blockberry', 12, 12, 'Orbit', true),
(40, 'IZ*ONE', 'IZONE', '아이즈원', '2018-10-29', 'Off The Record', 12, 12, 'WIZ*ONE' false),
(41, 'Cherry Bullet', null, '체리블렛', '2019-01-21', 'FNC', 7, 10, 'Lullet', true),
(42, 'ITZY', null, '있지', '2019-02-12', 'JYP', 5, 5, 'MIDZY', true),
(43, 'Everglow', null, '에버글로우 ', '2019-03-18', 'Yuehua', 6, 6, 'Forever', true),
(44, 'Rocket Punch', null, '로켓펀치', '2019-08-07', 'Woollim', 6, 6, 'Ketchy', true),
(45, 'Hinapia', null, '희나피아', '2019-11-03', 'Alseubit', 5, 5, 'UBY', false);

Presto SQL- convert date which is in string datatypes into date format yyyy/mm/dd

ds: date in the yyyy/mm/dd format. It is stored in the form of text and we use presto to run. no need for date function
CREATE TABLE job_data(
ds DATE,
job_id INT NOT NULL,
actor_id INT NOT NULL,
event VARCHAR(15) NOT NULL,
language VARCHAR(15) NOT NULL,
time_spent INT NOT NULL,
org CHAR(2) );
INSERT INTO job_data (ds, job_id, actor_id, event, language, time_spent, org)
VALUES ('2020-11-30', 21, 1001, 'skip', 'English', 15, 'A'),
('2020-11-30', 22, 1006, 'transfer', 'Arabic', 25, 'B'),
('2020-11-29', 23, 1003, 'decision', 'Persian', 20, 'C'),
('2020-11-28', 23, 1005,'transfer', 'Persian', 22, 'D'),
('2020-11-28', 25, 1002, 'decision', 'Hindi', 11, 'B'),
('2020-11-27', 11, 1007, 'decision', 'French', 104, 'D'),
('2020-11-26', 23, 1004, 'skip', 'Persian', 56, 'A'),
('2020-11-25', 20, 1003, 'transfer', 'Italian', 45, 'C');
here i have used ds as date datatype.
my code:
select ds, count(job_id) as jobs_per_day, sum(time_spent)/3600 as hours_spent
from job_data
where ds >='2020-11-01' and ds <='2020-11-30'
group by ds ;
This is what I have done but I have to enter date in string and I
can't understand how can I convert it into date without using any
function. I am using mysql workbench 8.0.
You can't convert a string to date without a function . In Presto you can use date_parse. Try:
select cast(date_parse(ds,'%Y-%m-%d') as date) as the_date ,
count(job_id) as jobs_per_day,
sum(time_spent)/3600 as hours_spent
from job_data
where the_date >='2020-11-01' and the_date <='2020-11-30'
group by the_date ;

Calculate the number of jobs reviewed per hour per day for November 2020?

This question is really confusing me. They didn't provide enough details of it. Whatever they have provided I have written below.
job_id: unique identifier of jobs
actor_id: unique identifier of actor
event: decision/skip/transfer
language: language of the content
time_spent: time spent to review the job in seconds
org: organization of the actor
ds: date in the yyyy/mm/dd format. It is stored in the form of text and we use presto to run. no need for date function
CREATE TABLE job_data
(
ds DATE,
job_id INT NOT NULL,
actor_id INT NOT NULL,
event VARCHAR(15) NOT NULL,
language VARCHAR(15) NOT NULL,
time_spent INT NOT NULL,
org CHAR(2)
);
INSERT INTO job_data (ds, job_id, actor_id, event, language, time_spent, org)
VALUES ('2020-11-30', 21, 1001, 'skip', 'English', 15, 'A'),
('2020-11-30', 22, 1006, 'transfer', 'Arabic', 25, 'B'),
('2020-11-29', 23, 1003, 'decision', 'Persian', 20, 'C'),
('2020-11-28', 23, 1005,'transfer', 'Persian', 22, 'D'),
('2020-11-28', 25, 1002, 'decision', 'Hindi', 11, 'B'),
('2020-11-27', 11, 1007, 'decision', 'French', 104, 'D'),
('2020-11-26', 23, 1004, 'skip', 'Persian', 56, 'A'),
('2020-11-25', 20, 1003, 'transfer', 'Italian', 45, 'C');
Below is the data. Points to be considered :
What does the event mean? What to consider for reviewing?
And here's the query I've tried:
SELECT ds, COUNT(*)/24 AS no_of_job
FROM job_data
WHERE ds BETWEEN '2020-11-01' AND '2020-11-30'
GROUP BY ds;
Check below approach if it is what you are looking for.
select ds,count(job_id) as jobs_per_day, sum(time_spent)/3600 as hours_spent
from job_data
where ds >='2020-11-01' and ds <='2020-11-30'
group by ds ;
Demo MySQL 5.6: https://www.db-fiddle.com/f/7yUJcuMJPncBBnrExKbzYz/26
Demo MySQL 8.0.26: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=83e89a2ad2a7e73b7ca990ac36ae4df0
The difference between the demos as #FaNo_FN pointed out in the comments is: in MySQL 8.0.26version it will provide an error if date 2020-11-31 it is used, because there is no 31 Novembre.
Use and condition instead of between , it performs faster.
You need to sum the time_spent for the day.

badge system / MySQL GROUP BY and ORDER BY

I'm creating a badge system for my website: the screenshot below shows you how it looks now. You receive badges with multiple levels (bronze, silver...) after earning 10,100 etc points for specific actions (such as answering a question, correcting a wiki). Note that the looking glass with the dollar sign is there two times, one in silver and one in bronze:
The underlying are two tables, one with the badge informations (x_badges: stores what action and how many points in it gives you what badge level), one with which user has earned which badge (x_badges_earned: badgeID and uID).
Explanation of FKs:
uID is the user ID, passed as parameter (use 1 for tests)
xb_ID is the auto_increment ID for each badge type
xbe_ID is the auto_increment ID of the row that matches userIDs to the ID of the badges they have earned (xb_ID -> uID)
This was my original query, which gives me only one badge of each category (but not the highest, ie if I have earned silver and bronze in one category it'll return only bronze):
SELECT *
FROM x_badges_earned, x_badges
WHERE xbe_bID = xb_ID
AND xbe_uID = ?
GROUP BY xb_requirement
ORDER BY xb_requirement ASC, xb_requirement_value ASC
After research on SO, I created this query which generates the above screenshot. If I change the last GROUP BY to xb_requirement, I'm back with the results from query 1:
SELECT b.*
FROM x_badges b
LEFT JOIN x_badges b2 ON b.xb_ID = b2.xb_ID
AND b.xb_requirement_value < b2.xb_requirement_value
LEFT JOIN x_badges_earned be ON be.xbe_bID = b.xb_ID
WHERE b2.xb_requirement_value IS NULL
AND be.xbe_uID = ?
GROUP BY b.xb_ID
I feel like I'm pretty much going in circles at this moment. I have come up with this which probably would work (at least in my head) but I can't solve it:
SELECT *
FROM x_badges
WHERE xb_ID IN (
SELECT xb_ID, MAX(xb_requirement_value)
FROM x_badges_earned, x_badges
WHERE xbe_bID = xb_ID AND xbe_uID = ?
GROUP BY xb_requirement
)
Any help is greatly appreciated!
I have attached the MySQL code to create the two tables and populate them to play around. Furthermore, you can use 1 as parameter value since it's my userID. My current output looks like this, the desired output would be the same without the first row (xb_ID 11) since it's a bronze badge for which I have earned silver.
CREATE TABLE `x_badges` (
`xb_ID` int(11) NOT NULL,
`xb_requirement` varchar(40) NOT NULL,
`xb_requirement_value` int(11) NOT NULL,
`xb_text` text NOT NULL,
`xb_text_details` text NOT NULL,
`xb_icon` varchar(20) NOT NULL,
`xb_color` varchar(6) NOT NULL,
`xb_color_text` varchar(6) NOT NULL,
`xb_level_name` varchar(20) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `x_badges` (`xb_ID`, `xb_requirement`, `xb_requirement_value`, `xb_text`, `xb_text_details`, `xb_icon`, `xb_color`, `xb_color_text`, `xb_level_name`) VALUES
(11, 'added_interaction', 10, 'Added interactions', 'Received more than %d points adding interactions with target companies!', 'search-dollar', 'cc8e34', '', 'Bronze'),
(15, 'added_target', 10, 'Added targets', 'Received more than %s points adding target companies!', 'dollar-sign', 'cc8e34', '', 'Bronze'),
(16, 'asked_question', 10, 'Asked questions', 'Received more than %s points asking questions!', 'question', 'cc8e34', '', 'Bronze'),
(17, 'notified_colleagues_interaction', 10, 'Interactions shared with colleagues', 'Received more than %s points tagging colleagues in interactions added!', 'bullhorn', 'cc8e34', '', 'Bronze'),
(18, 'reply_accepted', 10, 'Helpful replies', 'Received more than %s points thanks to replies marked as helpful!', 'check-double', 'cc8e34', '', 'Bronze'),
(19, 'reply_question', 10, 'Replies to questions', 'Received more than %s points replying to questions!', 'comments', 'cc8e34', '', 'Bronze'),
(20, 'updated_info', 10, 'Updated target profiles', 'Received more than %s points updating profiles of targets!', 'funnel-dollar', 'cc8e34', '', 'Bronze'),
(21, 'updated_wiki', 10, 'Updated wiki', 'Received more than %s points updating profiles of Group companies!', 'pen-nib', 'cc8e34', '', 'Bronze'),
(22, 'upvote_question', 10, 'Helpful questions', 'Received more than %s points for having own questions upvoted!', 'grin-alt', 'cc8e34', '', 'Bronze'),
(23, 'added_interaction', 100, 'Added interactions', 'Received more than %s points adding interactions with target companies!', 'search-dollar', 'aaa9ad', '', 'Silver'),
(24, 'added_interaction', 500, 'Added interactions', 'Received more than %s points adding interactions with target companies!', 'search-dollar', 'ffd700', '495057', 'Gold'),
(25, 'updated_wiki', 1000, 'Updated Bertelsmann wiki', 'Received more than %s points asking questions!', 'pen-nib', 'b9f2ff', '495057', 'Diamond'),
(26, 'added_interaction', 1000, 'Added interactions', 'Received more than %s points adding interactions with target companies!', 'search-dollar', 'b9f2ff', '495057', 'Diamond'),
(27, 'added_interaction', 5000, 'Added interactions', 'Received more than %s points adding interactions with target companies!', 'search-dollar', 'e0115f', '', 'Ruby');
CREATE TABLE `x_badges_earned` (
`xbe_ID` int(11) NOT NULL,
`xbe_uID` int(11) NOT NULL,
`xbe_bID` int(11) NOT NULL,
`xbe_timestamp` timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `x_badges_earned` (`xbe_ID`, `xbe_uID`, `xbe_bID`, `xbe_timestamp`) VALUES
(19, 1, 11, '2020-03-23 15:24:54'),
(20, 1, 15, '2020-03-23 15:24:54'),
(21, 1, 16, '2020-03-23 15:24:54'),
(22, 1, 17, '2020-03-23 15:24:54'),
(23, 1, 18, '2020-03-23 15:24:54'),
(24, 1, 19, '2020-03-23 15:24:54'),
(25, 1, 23, '2020-03-23 16:00:51'),
(26, 1, 20, '2020-03-23 15:32:31'),
(27, 1, 21, '2020-03-23 15:32:31'),
(28, 1, 22, '2020-03-23 15:32:31'),
(29, 10, 25, '2020-03-23 15:37:32');
db<>fiddle here
I have not found identifying expression for any definite badge except (xb_icon, xb_requirement_value) values pair (color is secondary, timestamp not guaranteed the ordering).
So the solution can be:
SELECT *
FROM x_badges xb
JOIN x_badges_earned xbe ON xb.xb_ID = xbe.xbe_bID
JOIN ( SELECT xb.xb_icon, MAX(xb.xb_requirement_value) xb_requirement_value
FROM x_badges xb
JOIN x_badges_earned xbe ON xb.xb_ID = xbe.xbe_bID
WHERE xbe.xbe_uID = #user
GROUP BY xb_icon ) max_earned ON (xb.xb_icon, xb.xb_requirement_value)
= (max_earned.xb_icon, max_earned.xb_requirement_value)
WHERE xbe.xbe_uID = #user;
fiddle
As a recommendation - normalize x_badges table, divide it to 2 separate tables - one stored a badge type data, and another stored level-related data with the reference to first table.

Calculate difference timestamp based on status (on/off)

Im trying to calculate the totale (daily) uptime and the total downtime in MySQL. I got the follow database:
CREATE TABLE `IOT_DATA` (
`DATA_ID` int(11) NOT NULL,
`DATA_BRON` text NOT NULL,
`DATA_SOORT` text NOT NULL,
`DATA_WAARDE` int(11) NOT NULL,
`DATA_TIJD` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `IOT_DATA` (`DATA_ID`, `DATA_BRON`, `DATA_SOORT`, `DATA_WAARDE`, `DATA_TIJD`) VALUES
(931, '77', 'temperature', 29, '2019-06-11 14:05:00'),
(932, '77', 'humidity', 32, '2019-06-11 14:05:00'),
(933, '77', 'temperature', 30, '2019-06-11 14:10:01'),
(934, '77', 'humidity', 32, '2019-06-11 14:10:01'),
(935, '77', 'temperature', 30, '2019-06-11 14:15:00'),
(936, '77', 'humidity', 31, '2019-06-11 14:15:00'),
(963, '77', 'status', 0, '2019-06-11 14:17:19'),
(978, '77', 'status', 1, '2019-06-11 14:18:40'),
(982, '77', 'temperature', 29, '2019-06-11 14:20:00'),
(983, '77', 'humidity', 32, '2019-06-11 14:20:00'),
(993, '77', 'status', 0, '2019-06-11 14:22:40'),
(1008, '77', 'status', 1, '2019-06-11 14:23:21'),
(1019, '77', 'status', 0, '2019-06-11 14:24:50'),
(1044, '77', 'temperature', 30, '2019-06-11 14:25:00'),
(1045, '77', 'humidity', 32, '2019-06-11 14:25:00'),
ALTER TABLE `IOT_DATA`
ADD PRIMARY KEY (`DATA_ID`);
ALTER TABLE `IOT_DATA`
MODIFY `DATA_ID` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1070;
It saves all sensor data from a machine. The 'DATA_SOORT' "status" indicates if the machine is started (1) or stopped (0).
I do not have a clue where to begin, I searched for comparable topics and got this:
select
date,
DATA_ID,
sum(datediff(minute, starttime, endtime )) downtime
from (
select
cast(t1.DATA_TIJD as date) as date,
t1.serviceid,
min(t1.DATA_TIJD) starttime,
ca.DATA_TIJD endtime
from IOT_DATA t1
cross apply (
select top 1 DATA_TIJD
from IOT_DATA
where serviceid = t1.serviceid
and DATA_TIJD > t1.DATA_TIJD
and DATA_SOORT = "status"
and DATA_WAARDE in (1)
order by DATA_TIJD
) ca
where t1.DATA_ID in (0)
group by cast(t1.DATA_TIJD as date), t1.DATA_ID, ca.DATA_TIJD
) a
group by date, DATA_ID;
It's not working, and honestly have no idea what it is. It gives the follow error:
- Incorrect parameter count in the call to native function 'datediff'
So i searched for that error and got something like it only can handle two expressions? But im not even sure if this is the correct way.
The expected result should be like
+------------+--------+----------+------------+--------------+
| Date | Source | TotaleUp | TotaleDown | PercentageUp |
+------------+--------+----------+------------+--------------+
| 11-06-2019 | 77 | 04:30:20 | 3:30:40 | 56% |
| 12-06-2019 | 77 | 06:00:00 | 1:00:00 | 85% |
+------------+--------+----------+------------+--------------+
The source = DATA_BRON
PercentageUP = Totaleup/(Totaleup+TotaleDown)*100
It is my first topic, if anything is missing please let me know