Maria DB SQL Code and Stored Procedure giving different Output - mysql

SQL Code is mentioned here , please have a look at this.
SELECT concat('{"workbenchStatsByUser": [', GROUP_CONCAT(js SEPARATOR ','))
FROM
(
SELECT json_object('username', workbenchStatsByUser, 'workbenchStatsByStatus',
JSON_ARRAY(GROUP_CONCAT( json_object( 'status', TempStatus, 'count', IFNULL(count, 0) ) SEPARATOR ','))) AS Js
FROM
(
SELECT
CASE WHEN username IS NULL THEN 'Not Assigned'
ELSE CONCAT(username,' - ', rolename)
END AS workbenchStatsByUser,
TempStatus,
COUNT(TempStatus) AS count
FROM users u
INNER JOIN tempOrgId t ON u.OrgId = t.OrgId
CROSS JOIN TempStatus ts
LEFT JOIN roles r ON r.id = u.roleid
LEFT JOIN vtask vt ON u.username = vt.updatedby AND ts.TempStatus = vt.status
GROUP BY workbenchStatsByUser, TempStatus
) A
GROUP BY workbenchStatsByUser
) B;
Username is null even-though their is a proper value.

Try changing
CASE WHEN username IS NULL THEN 'Not Assigned'
ELSE CONCAT(username,' - ', rolename)
END AS workbenchStatsByUser,
to
COALESCE(CONCAT(username,' - ', rolename), 'Not Assigned') AS workbenchStatsByUser,

Related

Subquery is not identifying column of main query

Error is
"Error in query (1054): Unknown column 'nt.id' in 'where clause'"
This the query
SELECT
nt.from as 'SENDER EMP ID',
if(nt.notification_time IS NOT NULL, nt.notification_time, nt.notification_start_time) as 'NOTIFICATION TIME',
nt.delivery_type as 'NOTIFICATION TYPE',
eh.first_name as 'SENDER FIRST NAME',
eh.last_name as 'SENDER LAST NAME',
eh.site_name as 'SENDER SITE NAME',
nt.title as 'NOTIFICATION TITLE',
nt.body as 'NOTIFICATION BODY',
(
select count(DISTINCT notifiable_id)
from notifications.notifications
where nt.id = notifications.notification_template_id
) as SEND TO No. OF USERS,
(
select GROUP_CONCAT('\n', counts_per_desig ) as counts
from
(
select
concat (if(quartz.employee_hierarchy.designation, quartz.employee_hierarchy.designation, "Un Assigned"), " : ", count(*) ) as counts_per_desig
from notifications.notifications
LEFT JOIN quartz.employee_hierarchy ON quartz.employee_hierarchy.employee_id = notifications.notifications.notifiable_id
where notifications.notifications.notification_template_id = nt.id
AND notifications.read_at IS NOT NULL
Group By quartz.employee_hierarchy.designation
) as 'READ BY No. OF USERS'
)
FROM notifications.notification_template AS nt
LEFT JOIN quartz.employee_hierarchy as eh ON eh.employee_id = nt.from
where (nt.created_by_type = 1)
and eh.location_id in (22, 123, 332)
and nt.from not in (185994, 81016, 168090, 24799, 104967)
There is a problem in this portion so code (subquery)
select GROUP_CONCAT('\n',counts_per_desig ) as counts
from
(
select concat (if(quartz.employee_hierarchy.designation,quartz.employee_hierarchy.designation,"Un Assigned")," : ",count(*) ) as counts_per_desig
from notifications.notifications
LEFT JOIN quartz.employee_hierarchy ON quartz.employee_hierarchy.employee_id = notifications.notifications.notifiable_id
where notifications.notifications.notification_template_id = 123
AND notifications.read_at IS NOT NULL
Group By quartz.employee_hierarchy.designation
) as 'READ BY No. OF USERS'
Your problem is that you are one level too deep. Unfortunately it is not possible to access a column name in a sub sub query.
You must hence move the join criteria (the notification template ID) one level up. Change:
(
select GROUP_CONCAT('\n', counts_per_desig ) as counts
from
(
select
concat (if(quartz.employee_hierarchy.designation, quartz.employee_hierarchy.designation, "Un Assigned"), " : ", count(*) ) as counts_per_desig
from notifications.notifications
LEFT JOIN quartz.employee_hierarchy ON quartz.employee_hierarchy.employee_id = notifications.notifications.notifiable_id
where notifications.notifications.notification_template_id = nt.id
AND notifications.read_at IS NOT NULL
Group By quartz.employee_hierarchy.designation
) as 'READ BY No. OF USERS'
)
to
(
select group_concat('\n', counts_per_desig)
from
(
select
n.notification_template_id,
concat(coalesce(ne.designation, 'unassigned'), ' : ', count(*)) as counts_per_desig
from notifications.notifications n
left join quartz.employee_hierarchy ne on ne.employee_id = n.notifiable_id
where n.read_at is not null
group by n.notification_template_id, ne.designation
) designations
where designations.notification_template_id = nt.id
) as read_by_no_of_users

MySQL IF distinct problem - why are my records not unique?

I have a sql query like this :
SELECT DISTINCT Users.UserID,Users.UserInfo,UserType.UserTypeName,
IF(Users.UserID IN (SELECT DISTINCT Aproved.UserID FROM Aproved WHERE DATE(Aproved.Date)= '2020-07-12'),'İzinli',
IF(Users.UserID IN (SELECT DISTINCT CheckInLog.UserID FROM CheckInLog WHERE DATE(CheckInLog.CheckTime)= '2020-07-12' AND CheckInLog.CheckType=1) ,'Başladı','Giriş Yapmadı') ) AS 'Status' ,
IF(Users.UserID IN (SELECT DISTINCT CheckInLog.UserID FROM CheckInLog WHERE DATE(CheckInLog.CheckTime)= '2020-07-12' AND CheckInLog.CheckType=1),
(SELECT DISTINCT CheckInLog.CheckTime FROM CheckInLog WHERE DATE(CheckInLog.CheckTime)= '2020-07-12' AND CheckInLog.UserID=Users.UserID AND CheckInLog.CheckType=1),' - ') AS 'Start' ,
IF(Users.UserID IN (SELECT DISTINCT CheckInLog.UserID FROM CheckInLog WHERE DATE(CheckInLog.CheckTime)= '2020-07-12' AND CheckInLog.CheckType=2),
(SELECT DISTINCT CheckInLog.CheckTime FROM CheckInLog WHERE DATE(CheckInLog.CheckTime)= '2020-07-12' AND CheckInLog.UserID=Users.UserID AND CheckInLog.CheckType=2),' - ') AS 'End'
FROM Users
JOIN UserType ON Users.UserType=UserType.UserTypeID
Where Users.UserType != 1 and Users.UserType != 2
This give me data like:
But I want data to be like
My check-in log table is like:
CheckType =1 -> Start
CheckType =2 -> End
Please help me guys. Thank you.
Users should be duplicated in the users table, so it is not clear what is going on. However, you can simplify your query considerably:
SELECT u.UserID, u.UserInfo, ut.UserTypeName,
(CASE WHEN s.UserID IN (SELECT a.UserID FROM Aproved a WHERE DATE(Aproved.Date)= '2020-07-12')
THEN 'İzinli'
WHEN u.UserID IN (SELECT cil.UserID FROM CheckInLog cil WHERE DATE(cil.CheckTime)= '2020-07-12' AND cil.CheckType = 1)
THEN 'Başladı'
ELSE 'Giriş Yapmadı'
END) AS Status,
(CASE WHEN u.UserID IN (SELECT cil.UserID FROM CheckInLog cil WHERE DATE(cil.CheckTime) = '2020-07-12' AND cil.CheckType = 1),
THEN (SELECT cil.CheckTime FROM CheckInLog cil WHERE DATE(cil.CheckTime) = '2020-07-12' AND cil.UserID = u.UserID AND cil.CheckType = 1),
ELSE ' - '
END) AS Start ,
(CASE WHEN u.UserID IN (SELECT cil.UserID FROM CheckInLog cil WHERE DATE(c.cil) = '2020-07-12' AND cil.CheckType = 2)
THEN (SELECT cil.CheckTime FROM CheckInLog cil WHERE DATE(cil.CheckTime) = '2020-07-12' AND cil.UserID = u.UserID AND cil.CheckType = 2),
ELSE ' - '
END) AS `End`
FROM Users u JOIN
UserType ut
ON u.UserType = ut.UserTypeID
WHERE u.UserType NOT IN (1, 2);
I'm not sure if this will fix your particular problem. But note the following:
NOT IN is simpler than multiple comparisons.
Single quotes should only be used for string and date constants, not column names.
Table aliases make the query easier to write and read.
SELECT DISTINCT is not appropriate for an IN subquery.
CASE is the standard form for conditional logic in SQL and is more powerful because it allows multiple clauses.

MySQL - Way to set a default return value when NULL is found?

Is there a way in SQL to set a default return value when NULL is returned for part of the results?
Here is my SQL:
SELECT p.id, p.title, concat( u1.meta_value, ' ', u2.meta_value ) as fullname, concat( r.name, ', ', c.name ) as location
FROM modules_profiles p
LEFT JOIN moonlight_usermeta u1 ON p.user_id = u1.user_id AND u1.meta_key = 'first_name'
LEFT JOIN moonlight_usermeta u2 ON p.user_id = u2.user_id AND u2.meta_key = 'last_name'
LEFT JOIN modules_regions r ON r.id = p.region_id
LEFT JOIN modules_countries c ON c.id = p.country_id
WHERE p.certification IN ( 'certified' ) AND p.country_id IN ( 2 )
ORDER BY p.user_id ASC
There are times when there is no region_id set for a given profile; therefore, NULL is returned for location for that respective user_id, even though we do have a country's name (c.name).
Is there a way in this case to just return the c.name only?
Use COALESCE() function like below, it will return the first non NULL value provided in list
COALESCE(col_name, 'default_value')
For your case, do
COALESCE(region_id, c.name)
I think, you are specifically talking about the part
concat( r.name, ', ', c.name ) as location
You can modify this using CASE expression as well
case when r.name is not null and c.name is not null
then concat( r.name, ', ', c.name ) else c.name end as location
You want to use MySQL's IFNULL(value, default) function.
Coalesce could help you
COALESCE(region_id, 'default value')

Rows are represented as columns in a View

for my sense, I've a creative way of saving userdata. Let me explain:
I do not know which data is going to be saved in this database. For example, someone wants to save his icq number and i didn't know it before, where could he write it into? He dynamically creates a new field and in background there is an insert done in fields and an insert in user_fields where the new value of the new option is stored.
Table user:
id username
1 rauchmelder
Table fields:
id name
1 firstname
2 lastname
Table user_fields: (old values are stored as well as current, only youngest entry should be used)
id user_id fields_id value date
1 1 1 Chris 1.Mai
1 1 2 Rauch 1.Mai
1 1 1 Christopher 2.Mai
Result should be a View:
user.id user.username fields.firstname fields.lastname
1 rauchmelder Christopher Rauch
Firstly, does it make sense at all?
Secondly, should I solve it in MySQL or within the application?
Thridly, how to solve this in MySQL as a View?
In order to get the data into your columns, you can use an aggregate function with a CASE expression to convert the row data into columns.
If your fields are known ahead of time, then you can hard-code the values in your query:
select u.id,
u.username,
max(case when f.name = 'firstname' then uf.value end) firstname,
max(case when f.name = 'lastname' then uf.value end) lastname
from user u
left join
(
select uf1.*
from user_fields uf1
inner join
(
select max(date) maxDate, user_id, fields_id
from user_fields
group by user_id, fields_id
) uf2
on uf1.date = uf2.maxdate
and uf1.user_id = uf2.user_id
and uf1.fields_id = uf2.fields_id
) uf
on u.id = uf.user_id
left join fields f
on uf.fields_id = f.id
group by u.id, u.username;
See SQL Fiddle with Demo
But since you are going to have unknown fields, then you will need to use a prepared statement to generate dynamic SQL to execute. The syntax will be similar to this:
SET #sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(CASE WHEN f.name = ''',
name,
''' THEN uf.value END) AS `',
name, '`'
)
) INTO #sql
FROM fields;
SET #sql
= CONCAT('SELECT u.id,
u.username, ', #sql, '
from user u
left join
(
select uf1.*
from user_fields uf1
inner join
(
select max(date) maxDate, user_id, fields_id
from user_fields
group by user_id, fields_id
) uf2
on uf1.date = uf2.maxdate
and uf1.user_id = uf2.user_id
and uf1.fields_id = uf2.fields_id
) uf
on u.id = uf.user_id
left join fields f
on uf.fields_id = f.id
group by u.id, u.username');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
See SQL Fiddle with Demo

MySQL query: Using UNION and getting row number as part of SELECT

I have a union query as follows:
(SELECT t.id, t.name, c.company AS owner, t.creation_date AS date, t.notes
FROM tool t, client c
WHERE t.id_customer = '15' AND t.trash_flag = '1')
UNION
(SELECT f.id, f.name, CONCAT(m.first_name, ' ', m.last_name) AS owner, f.date, f.notes
FROM file f, meta m
WHERE ((f.acl = 0) OR (f.acl = 1 AND '1' = TRUE) OR (f.acl = 2 AND f.id = '7')) AND f.id = '15' AND f.trash_flag = '1' AND m.user_id = f.id_user)
ORDER BY 'name' 'ASC' LIMIT 0,20
Everything works fine but I have two questions:
How do I add a column to the entire result set that gives the row number
Could I do this without using UNION e.g. an advanced join?
Thanks for your time MySQL gurus!
I can't test it righ now but from what I found, following might work:
Reference: Row Number Variable
SQL Statement
SELECT #rownum := #rownum + 1 rownum
, t.*
FROM (
(SELECT t.id
, t.name
, c.company AS owner
, t.creation_date AS date
, t.notes
FROM tool t
, client c
WHERE t.id_customer = '15'
AND t.trash_flag = '1'
) UNION (
SELECT f.id
, f.name
, CONCAT(m.first_name, ' ', m.last_name) AS owner
, f.date
, f.notes
FROM file f
, meta m
WHERE ((f.acl = 0) OR (f.acl = 1 AND '1' = TRUE) OR (f.acl = 2 AND f.id = '7')) AND f.id = '15' AND f.trash_flag = '1' AND m.user_id = f.id_user)
)
) t
, (SELECT #rownum := 0) r
ORDER BY
'name' ASC
LIMIT 0, 20