INSERT INTO not working with my select - sql

I need to copy some data from one table to another:
There is a table that has the correct date (AUDITLOG), column TIME but I need to put it in the USER table, column USERS_DATE and associate with the correct user...
The SELECT returns the correct data by itself, I'm having issue using the SELECT INTO statement. My hacked up code below:
INSERT INTO users (USERS_DATE) WHERE USERID=U.USERID
(SELECT U.USERID,
javaTimeStampToDate (L.TIME)
AS "Last Login"
FROM COMPANY C,
USERS U,
AUDITMAP M,
AUDITLOG L
WHERE C.COMPANYID = U.COMPANYID
AND U.USERID = M.ROWID
AND M.AUDITID = L.AUDITID
AND C.APPLICATION = 'A'
AND L.NOTES LIKE '%went inactive%'
AND U.STATUS = 0);

Try with the below query for sql server.
I think you need an update query. Also change your commas with JOIN condition.
UPDATE U
SET U.USERS_DATE=L.TIME
FROM COMPANY C
JOIN USERS U ON C.COMPANYID = U.COMPANYID
JOIN AUDITMAP M ON U.USERID = M.ROWID
JOIN AUDITLOG L ON M.AUDITID = L.AUDITID
WHERE C.APPLICATION = 'A'
AND L.NOTES LIKE '%went inactive%'
AND U.STATUS = 0
use below query for oracle,
MERGE INTO USERS U
USING
(
SELECT M.ROWID,L.Time
FROM AUDITMAP M
JOIN AUDITLOG L ON M.AUDITID = L.AUDITID
WHERE L.NOTES LIKE '%went inactive%'
) Au ON (U.USERID = Au.ROWID)
WHEN MATCHED THEN UPDATE
SET U.USERS_DATE = Au.TIME
WHERE U.STATUS = 0 AND EXISTS (select 1
from COMPANY c
where .COMPANYID = U.COMPANYID AND C.APPLICATION = 'A')

Related

Select totals to return only one record in SQL Server

After spending more than 3 hours on this I gave up.
I have four tables:
Users, Approvals, Centers, Managements
My ultimate goal is to get the total number of users in each management separated by the user role (I have two roles here : Parents and Society members)
I've been using the following code
select
(select count(r.StudentId)
from Users u
where u.UserId = r.StudentId and u.RoleId = 10) as Parents,
(select count(r.StudentId)
from Users u
where u.UserId = r.StudentId and u.RoleId = 11) as SocietyMembers,
e.ManagementId, e.ManagmentTitle
from
CentersRegistrationsApprovals r --ON r.StudentId = u.UserId
inner join
Centers c ON c.CenterId = r.CenterId
inner join
Managments e ON e.ManagementId = c.EducationManagementId
group by
e.ManagementId, e.ManagmentTitle, StudentId
I'm expecting the query result to be as the following :
Parents SocietyMambers ManagementId ManagementName
----------------------------------------------------------------
3 3 10 North Region
However the result set always gives me
Parents SocietyMambers ManagementId ManagementName
----------------------------------------------------------------
3 NULL 10 North Region
NULL 3 10 North Region
Any ideas how to consolidate the result to only 1 record?
You can query like below:
select
Sum(case when u.roleId = 10 then 1 else 0 end) as Parents,
Sum(case when u.roleId = 11 then 1 else 0 end) as SocietyMembers,
e.ManagementId, e.ManagmentTitle
from
CentersRegistrationsApprovals r --ON r.StudentId = u.UserId
inner join
Centers c ON c.CenterId = r.CenterId
inner join
Managments e ON e.ManagementId = c.EducationManagementId
Join Users u ON r.StudentId = u.UserId
group by
e.ManagementId, e.ManagmentTitle
Please try something like this (not tested)
; with CTE1 as (
select
(select count(r.StudentId)
from Users u
where u.UserId = r.StudentId and u.RoleId = 10) as Parents,
(select count(r.StudentId)
from Users u
where u.UserId = r.StudentId and u.RoleId = 11) as SocietyMembers,
e.ManagementId, e.ManagmentTitle
from
CentersRegistrationsApprovals r --ON r.StudentId = u.UserId
inner join
Centers c ON c.CenterId = r.CenterId
inner join
Managments e ON e.ManagementId = c.EducationManagementId
group by
e.ManagementId, e.ManagmentTitle, StudentId
)
SELECT MAX(Parents), MAX(SocietyMembers), ManagementId, StudentId
FROM CTE1
GROUP BY ManagementId, StudentId

sql : query same column multiple times AS different columns, with multiple values returned 1 per row

I need to build a report that is structured as follows:
Name, Field_1, Field_2, Field_3
Jim, opt_1, y, 12
Jane, opt_2, n, 64
etcetera
I'm pulling from Moodle database tables, structure shown in following images. mdl_user_info_data, mdl_user_info_field, mdl_user has same columns as others, all I'm getting from it is name so I'm not bothering to include it here. That part works fine.
Here's the best I could come up with so far, so you can see how the tables join:
SELECT
CONCAT (u.firstname, u.lastname) Name,
(SELECT d.data FROM mdl_user_info_data d JOIN mdl_user_info_field f ON f.id = d.fieldid WHERE f.shortname = "Field_1" GROUP BY d.userid),
(SELECT d.data FROM mdl_user_info_data d JOIN mdl_user_info_field f ON f.id = d.fieldid WHERE f.shortname = "Field_2" GROUP BY d.userid),
(SELECT d.data FROM mdl_user_info_data d JOIN mdl_user_info_field f ON f.id = d.fieldid WHERE f.shortname = "Field_3" GROUP BY d.userid),
FROM mdl_user u
JOIN mdl_user_info_data d ON d.userid = u.id
JOIN mdl_user_info_field f ON d.fieldid = f.id
GROUP BY d.userid
ORDER BY `Name` ASC
I know I'm barking up the wrong tree with my sub-queries, but not sure what to do in place of the GROUP BYs. My current query will return all values of each given Field_x for in each row, when I need to return only the value that corresponds to the user named in column 1.
Any help much appreciated.
I'm not positive about moodle or it's sql syntax, but if common, you might get what you want by doing left-joins to the table multiple times, each with its criteria qualification, then just use the different ALIAS references to get your pieces...
SELECT
CONCAT (u.firstname, u.lastname) Name,
dFld1.Data as Field1Data,
dFld2.Data as Field2Data,
dFld3.Data as Field3Data
FROM
mdl_user u
LEFT JOIN mdl_user_info_data dFld1
ON u.id = dFld1.userid
LEFT JOIN mdl_user_info_field fFld1
ON dFld1.fieldid = fFld1.id
AND fFld1.shortname = "Field_1"
LEFT JOIN mdl_user_info_data dFld2
ON u.id = dFld2.userid
LEFT JOIN mdl_user_info_field fFld2
ON dFld2.fieldid = fFld2.id
AND fFld2.shortname = "Field_2"
LEFT JOIN mdl_user_info_data dFld3
ON u.id = dFld3.userid
LEFT JOIN mdl_user_info_field fFld3
ON dFld3.fieldid = fFld3.id
AND fFld3.shortname = "Field_3"
ORDER BY
`Name` ASC
I have this query with LEFT-JOINs if any such links may NOT have a value.
As for the group by, this would only be required if there are multiple entries for one or more of the underlying tables for a given user and field 1, 2 or 3 entries respectively.
An alternative solution.
SELECT u.id, u.firstname, u.lastname, f.fieldname1, f.fieldname2
FROM mdl_user u
JOIN (
SELECT d.userid,
MAX(CASE WHEN f.shortname = 'fieldname1' THEN d.data ELSE null END) AS fieldname1,
MAX(CASE WHEN f.shortname = 'fieldname2' THEN d.data ELSE null END) AS fieldname2
FROM mdl_user_info_field f
JOIN mdl_user_info_data d ON d.fieldid = f.id
WHERE f.shortname IN ('fieldname1', 'fieldname2')
GROUP BY d.userid) f ON f.userid = u.id
Concat will work for MySql, but you should use database compatible functions - https://docs.moodle.org/dev/Data_manipulation_API#SQL_compatibility_functions
So use the result of
$DB->sql_concat('u.firstname', 'u.lastname');

Better ways to write this SQL Query

I have the below table structure
Users (PK - UserId)
System (PK - SystemId)
SystemRoles (PK-SystemRoleId, FK - SystemId)
UserRoles (PK-UserId & SystemRoleId, FK-SystemRoleId, FK-UserId)
Users can have access to different Systems and one System can have different SystemRoles defined.
Now, I need to delete Users who have SystemRoles assigned to them ONLY for a specific System(s). If they have SystemRoles defined for other Systems, they should not be deleted.
I have come up the below query to identify the records that are eligible for delete but think this can surely be optimized. Any suggestions?
SELECT U.*
FROM
(
SELECT
distinct UR.UserID
FROM
dbo.UserRole UR
INNER JOIN dbo.SystemRole SR ON (SR.SystemRoleID = UR.SystemRoleID)
INNER JOIN dbo.[System] S ON (S.SystemID = SR.SystemID)
WHERE
S.SystemName = 'ABC' OR S.SystemName = 'XYZ'
) T
INNER JOIN dbo.[User] U ON (U.UserID = T.UserID)
WHERE T.UserID NOT IN
(
select
distinct UR.UserID
from
dbo.[UserRole] UR
INNER JOIN dbo.SystemRole SR ON (SR.SystemRoleID = UR.SystemRoleID)
INNER JOIN dbo.[System] S ON (S.SystemID = SR.SystemID)
WHERE
S.SystemName <> 'ABC'
AND S.SystemName <> 'XYZ'
)
something like this?
select userid from (
SELECT
UR.UserID,
max(case when (S.SystemName = 'ABC' OR S.SystemName = 'XYZ')
then 1 else 0 end) as kill,
max(case when (S.SystemName <> 'ABC' AND S.SystemName <> 'XYZ')
then 1 else 0 end) as keep
FROM
dbo.UserRole UR
INNER JOIN dbo.SystemRole SR ON (SR.SystemRoleID = UR.SystemRoleID)
INNER JOIN dbo.[System] S ON (S.SystemID = SR.SystemID)
group by UR.UserID
) u where kill = 1 and keep = 0
This sort of structure will get you the records you need.
select yourfields -- or delete
from userroles
where userid in
(select userid
from userroles join etc
where system.name = the one you want
except
select userid
from userroles join etc
where system.name <> the one you want
)

How to return multiple values when using SELECT EXISTS in postgresql

I have the following SQL query:
SELECT EXISTS (SELECT r.id FROM Rules r INNER JOIN rule_t c on c.id=r.rule_t.id
INNER JOIN user u on u.id = r.user_id
WHERE u.fmnum='2813'
AND c.name='default') ::int
Is there a way I can modify this so that I get two values back, the INT from the EXISTS method, and r.id?
I know that I can change the query so that I remove the EXISTS method... if the sub select returns anything at all, then I know the record exists... but I'm just wondering if its possible to do the above.
Thanks.
EDIT 1
I'm testing the following code in a new query window in pgadmin3...
SELECT *
FROM (
SELECT TRUE, r.id
FROM rules r
JOIN rule_t c on c.id = r.rule_t.id
JOIN user u on u.id = r.user_id
WHERE u.fmnum = '2813'
AND c.name = 'default'
);
But I'm getting the following error:
ERROR: subquery in FROM must have an alias LINE 2: (
^ HINT: For example, FROM (SELECT ...) [AS] foo.
EDIT 2
SELECT *
FROM (
SELECT TRUE, r.id
FROM rules r
JOIN rule_t c on c.id = r.rule_t.id
JOIN user u on u.id = r.user_id
WHERE u.fmnum = '2813'
AND c.name = 'default'
) AS x;
SELECT 1 AS does_exist, r.id
FROM rules r
JOIN rule_t c on c.id = r.rule_t.id
JOIN user u on u.id = r.user_id
WHERE u.fmnum = '2813'
AND c.name = 'default'
LIMIT 1; -- may or may not be needed.
This does what you seem to be asking for: you get two columns. But you get no row if nothing is found.
If you want a row, even if nothing is found, you need a subquery:
SELECT sub.t_id IS NOT NULL AS does_exist, sub.id
FROM (SELECT 1) x -- dummy to guarantee 1 row
LEFT JOIN ( -- LEFT JOIN is crucial
SELECT r.id
FROM rules r
JOIN rule_t c on c.id = r.rule_t.id
JOIN user u on u.id = r.user_id
WHERE u.fmnum = '2813'
AND c.name = 'default'
LIMIT 1 -- may or may not be needed.
) ON TRUE; -- join condition is always true
Or, simpler / faster:
SELECT 1 AS does_exist, r.id
FROM rules r
JOIN rule_t c on c.id = r.rule_t.id
JOIN user u on u.id = r.user_id
WHERE u.fmnum = '2813'
AND c.name = 'default'
UNION ALL
SELECT 0, NULL
LIMIT 1;

SQL SELECT statement with users, roles and rights

Lets say that I have tables:
Users
Users_in_Roles
Roles
Rights_in_Roles
Rights
Keys are standard( UserFk, RoleFk, RightFk)
The question is: how to get all users that are in role with right X (id = 100)
I Have no idea how to touch this problem. Please help and sorry for my english.
SELECT [dbo].[System_Users].[Id]
,[UserName]
,[FirstName]
,[LastName]
,[Email]
,RoleFk
,[dbo].[System_Roles].Name
FROM [dbo].[System_Users]
INNER JOIN [dbo].[System_Roles_System_Users]
ON [dbo].[System_Roles_System_Users].UserFk = [dbo].[System_Users].Id
INNER JOIN [dbo].[System_Roles]
ON [dbo].[System_Roles].Id = [dbo].[System_Roles_System_Users].RoleFk
WHERE ?
I tryied sth like that, could you tell me what iw wrong?
SELECT
DISTINCT System_Users.Id,
System_Users.FullName
FROM System_Users
INNER JOIN Dict_Rights_System_Users
ON System_Users.Id = Dict_Rights_System_Users.UserFk
INNER JOIN System_Roles_System_Users
ON System_Roles_System_Users.UserFk = System_Users.Id
WHERE
RightFk = 136
OR
136 IN (SELECT Dict_Rights_System_Roles.RightFk FROM Dict_Rights_System_Roles WHERE
Dict_Rights_System_Roles.RoleFk = System_Roles_System_Users.RoleFk)
ORDER BY System_Users.FullName ASC
You will need to JOIN the tables on the key relationships. The basic structure will be:
select u.Id,
u.UserName,
u.FirstName,
u.LastName,
u.Email,
r.RoleFk,
r.Name RoleName,
rt.Name RightName
from users u
inner join users_in_roles ur
on u.id = ur.userfk
inner join roles r
on ur.rolefk = r.id
inner join rights_in_roles rr
on r.rolefk = rr.rolefk
inner join rights rt
on rr.rightfk = rt.id
where rt.id = 100
If you need help learning JOIN syntax here is a great reference:
A Visual Explanation of SQL Joins
You can try with this:
SELECT *
FROM Users u
WHERE EXISTS (
SELECT ur.RoleFk
FROM Users_in_Roles ur
WHERE u.UserPk = ur.UserFk
AND EXISTS
(
SELECT 1
FROM Rights_in_Roles rr
WHERE rr.RoleFk = ur.RoleFk
AND rr.RightFk = 100
)
)
OR EXISTS (
SELECT 1
FROM Users_Rights uri
WHERE u.UserPk = uri.UserFk
AND uri.RightFk = 100
)
Note that the above query doesn't return RoleFk and Name for the role.
Another approach would be:
SELECT u.Id
,u.UserName
,u.FirstName
,u.LastName
,u.Email
,rr.RoleFk
,r.Name
FROM Users u
-- get users that are in role that has right
LEFT JOIN
Users_in_Roles ur ON
ur.UserFk = u.UserPk
LEFT JOIN
Rights_in_Roles rr ON
rr.RoleFk = ur.RoleFk
AND rr.RightFk = 100
LEFT JOIN
Rights r ON
r.RolePk = rr.RoleFk
-- get users that have a right granted to them directly
LEFT JOIN
Users_Rights uri ON
u.UserPk = uri.UserFk
AND uri.RightFk = 100
WHERE rr.RoleFk IS NOT NULL OR uri.UserFk IS NOT NULL