selecting values from a reference table - mysql

I have a users table and have roles such as admin|manager|employee which are represented in reference table called reference.
user table - id|first_name|last_name|type|status
reference table - id|table|type|key|value
Now the reference table contains integer key that match values so user.type has 0-admin,1-manager,2-employee which looks something like this
table:user
type:type
key:0
value:admin
My problem is when I have to values in a table which need to access the reference table.
table:user
type:status
key:0
value:enabled
Question: How can I access two reference table values in one statement?
//STATEMENT
SELECT a.id,a.first_name,a.last_name,b.value as user_type,b.value as user_status
FROM user AS a
JOIN reference as b
ON 'user'=b.table AND 'type'=b.type AND a.type = b.value AND a.status = b.value

You can join to the reference table twice (or three times, or four times...). Just give it two different aliases:
SELECT a.id,a.first_name,a.last_name,b.value as user_type,b.value AS user_type, b2.value as user_status
FROM user AS a
JOIN reference AS b
ON 'user'=b.table AND 'type'=b.type AND a.type = b.value
JOIN reference AS b2
ON 'user'=b2.table AND 'status'=b2.type AND a.status = b2.value
Unless I'm mis-interpreting your requirements, I believe the above is what you are seeking.

Related

update from another table but join on calculated column

Table A has three columns; an IP address(varchar), lab ID(int), and origin (int).
Table B has two columns; an ID(int) and labName(varchar)
The labName is table B is made up of the IP address' first octet in A. For instance if the IP was 192.168.5.18 then there would be a lab name 'lab 192'. What I need to do is update Table A's labID column with the matching ID in table B.
I already have parsing done to build the lab name from the IP:
What I'm not sure how to do is the update based on that calculated field. Code below won't work but I'm hoping it might explain what I'm attempting to do:
UPDATE tableA
SET labID = (
SELECT labName
FROM tableB
WHERE labName = concat(β€˜lab β€˜, substring_index(ip, β€œ.”, 1)
)
WHERE origin = 3
MySQL will permit you to call a function (or any expression) in a join's ON clause using a join for the table_reference in UPDATE syntax
UPDATE
tableA
-- Join on the IP substring expression
INNER JOIN tableB ON tableB.labName = CONCAT('lab ', substring_index(tableA.ip, '.', 1))
-- Set labID to tableB ID
SET tableA.labID = tableB.ID
WHERE origin = 3

return values of table 1 based on single column in table 2

I have 3 tables that I am using and need to make a query to return data from one table based on the value of a single column in the second table.
tbl_user
ID
login
pass
active
mscID
tbl_master
ID
name
training_date
MSCUnit
Active
tbl_msc
mscID
mscName
my current SQL statement:
SELECT
tbl_master.ID,
tbl_master.name,
tbl_master.training_date,
tbl_master.MSCUnit,
tbl_master.active,
tbl_user.mscID
FROM
tbl_master,
tbl_user
WHERE
tbl_master.active = 1 AND tbl_master.MSCUnit = tbl_user.mscID
The values stored in tbl_msc.mscID is a varchar(11) and it contains a string similar to A00 or A19. This is also the Primary key in the table.
The values stored in tbl_user.mscID matches that of tbl_msc.mscID. The values stored in tbl_master.UnitMSC also matches that of tbl_msc.mscID.
My goal is to return all records from tbl_master where the currently logged in user has the same mscID. The problem I am having is the statement returns all records in tbl_master.
I have tried several different join statements and for some reason, I cannot get this to filter correctly.
I am missing something. Any assistance in the SQL statement would be appreciated.
Thanks,
Will
You should be writing this using joins. I don't know how you know who the current user is, but the idea is to join the three tables together:
SELECT m.ID, m.name, m.training_date, m.MSCUnit, m.active,
u.mscID
FROM tbl_master m JOIN
tbl_user u
ON m.MSCUnit = u.mscID JOIN
tbl_msc msc
ON msc.mscID = u.msc_ID
WHERE m.active = 1 AND msc.mscName = ?;
Notice the use of proper, explicit, standard JOIN syntax and table aliases.
Select a.*, b.userid from
table_master a, table_user b where
a.mscunit in (select mscid from
table_user where active=1)
This should point you in the right direction.

How to insert only edited values in table

I have table "nol_voa" with different values and I am importing xml file with values in that table I want to insert in another table "#tmpRcIzm" the "id" values where the field "C_REF" has changed its value.
This is the code, what I wrote, but there is a mistake, it always adds two more "id" values which have not been changed.
insert into #tmpRcIzm
select distinct
a.id
from
openxml(#hDoc, '/art_komplekts/nol_voa') with #vc xd
join nol_art a on xd.art_cd = a.cd
left join #tmp t on t.cd = xd.art_cd
inner join nol_voa v on xd.id_art = v.id_art
where
xd.C_REF!=v.C_REF
You left join of #tmp, can introduce duplicates, and also the join on nol_art serve no purpose on this SQL. remove those two, and you should elminate your dups.

Right way to do this query

I have a table
form (
int id )
webformsystemflags ( int id, int formid int sysflagid )
sysflag ( int id, name char(10) )
form table is a table which has all the forms
webform is a table which has the forms which have flags applied to it. It has a foreign key formid which is id to the form table and sysflagid which is foreign key to the sys flag table
sys flag is the table which contains the flags. Lets say I have flags defined as 1,2,3
I can have forms which don't have all the flags applied to it, some may have 1, some may have 2 or some may have 3 applied to it or some may have none.
How can I find all the forms which have either flag 1 or flag 2 or flag 3 applied to it ?
This is a common trick to find EXCLUSION. The value I have below of "FlagYouAreExpectingTo_NOT_Exist" is explicitly the one you expect NOT to be there. Here's how it works.
Get every form and LEFT JOIN to the Web System Flags table WITH FINDING the matching form, and flag setting you DO NOT want. If it finds a valid entry for the form and flag, the "formid" in the (wsf) table will exist. So, we want all that DON'T exist, hence the closing WHERE wsf.formid is null.
It will be NULL for those where it is NOT already flagged.
select
f.ID
from
forms f
left join webformsystemflags wsf
on f.id = wsf.formid
AND wsf.sysflagid = FlagYouAreExpectingTo__NOT__Exist
where
wsf.formid is null
You could use a subquery:
SELECT * FROM `form` WHERE `id` IN (SELECT `formid` FROM `webformsystemflags`)
Careful with subqueries on huge databases though. You could do the same thing with joins but this is an easy solution that will get you going.
Or for all results that DO NOT have a certain flag:
SELECT * FROM `form` WHERE `id` IN (SELECT `formid` FROM `webformsystemflags` WHERE `sysflagid` != 1 OR `sysflagid` != 2)
or a join method:
SELECT f.*, r.`sysflagid` FROM `form` f LEFT JOIN `webformsystemflags` r ON r.`formid` = f.`id` WHERE r.`sysflagid` != null
will get you the forms and the related flags. However, it will not get ALL flags in one row if the form has multiple flags on it. That one you may need to do a concat on the flags, but this answer is already growing unnecessarily complex.
*LAST EDIT *
Ok nutsandbolts - You need to update your question cause the two of us have overshot ourselves in a number of different queries and it isn't really helping to come back saying it doesnt give the right results. The right results can easily be reached by simply examining the queries we have provided and using the general logic behind them to compose the query that is right for you.
So my last suggestion - you say you want a query that will return a form IF it has a certain flag applied to it AND that is does NOT have other flags applied to it.
Here it is supposing you wanted all forms with a flag of 1 AND NOT 2 or 3 or none:
SELECT f.*, r.`sysflagid` FROM `form` f LEFT JOIN `webformsystemflags` r ON r.`formid` = f.`id` WHERE r.`sysflagid` =1 AND r.`formid` NOT IN (SELECT `formid` FROM `webformsystemflags` WHERE `sysflagid` = 2 OR `sysflagid` = 3)
Because your webformsystemflags is relational this query will NOT return any forms that do not exist in the webformsystemflags table - so you don't need to consider null.
If this is not what you're looking for I strongly suggest you rewrite your question with absolute and perfect clarity on your needs cause after this one I'm out of this conversation. Much luck to you though. Have fun.
You can use an exists clause to pull records like this:
select a.*
from form a
where exists (select 1
from webformsystemflags
where formid = a.id
and sysflagid IN (1,2,3))
This won't give you the associated flag. If you want that:
select a.*, b.sysflagid
from form a
join (select formid, sysflagid
from webformsystemflags
where sysflagid in (1,2,3)) b
on a.id = b.formid
There are many different ways to solve this.
EDIT: By reading a comment on the other answer it seems the question was unclear. You want the result forms that only have ONE flag? i.e. the form has flag 1 but not 2 or 3?
edit2: if you really just want a true/false query pulling only the true (has a flag):
select a.*, b.sysflagid
from form a
join webformsystemflags b on a.id = b.formid
If you want forms without flags:
select a.*
from form a
left join webformsystemflags b on a.id = b.formid
where b.formid is null
edit3: Based on comment, forms with one flag and not one of the others:
select a.*
from form a
where exists (select 1 from webformsystemflags where formid = a.id and sysflagid = 1)
and (
not exists (select 1 from webformsystemflags where formid = a.id and sysflagid = 2)
or
not exists (select 1 from webformsystemflags where formid = a.id and sysflagid = 3)
)

sql query for deleting rows with NOT IN using 2 columns

I have a table with a composite key composed of 2 columns, say Name and ID. I have some service that gets me the keys (name, id combination) of the rows to keep, the rest i need to delete. If it was with only 1 row , I could use
delete from table_name where name not in (list_of_valid_names)
but how do I make the query so that I can say something like
name not in (valid_names) and id not in(valid_ids)
// this wont work since they separately dont identity a unique record or will it?
Use mysql's special "multiple value" in syntax:
delete from table_name
where (name, id) not in (select name, id from some_table where some_condition);
If your list is a literal list, you can still use this approach:
delete from table_name
where (name, id) not in (select 'john', 1 union select 'sally', 2);
Actually, no I retract my comment about needing special juice or being stuck with (AND OR'ing all your options).
Since you have a list of values of what you want to retain, dump that into a temporary table. Then do a delete against the base table for what does not exist in the temporary table (left outer join). I suck at mysql syntax or I'd cobble together your query. Psuedocode is approximate
DELETE
B
FROM
BASE B
LEFT OUTER JOIN
#RETAIN R
ON R.key1 = B.key1
AND R.key2 = B.key
WHERE
R.key1 IS NULL
The NOT EXISTS version:
DELETE
b
FROM
BaseTable b
WHERE
NOT EXISTS
( SELECT
*
FROM
RetainTable r
WHERE
(r.key1, r.key2) = (b.key1, b.key2)
)