How to get the actual values from a SQL join table - sql

I have two tables [dbo].Notifications and [dbo].ClientsNotifications where :
[dbo].Notifications:
ID : Notification
1 : 'Notification1'
2 : 'Notification2'
3 : 'Notification3'
and so on...
and
[dbo].ClientsNotifications:
Id : ClientId : NotificationId
1 : 1 : 1
2 : 2 : 2
3 : 1 : 3
4 : 5 : 2
and so on..
What I want is by given ClientId to fetch all the string values from [dbo].Notifications.SELECT *
I tried something like this :
FROM [dbo].Notifications c, [dbo].ClientsNotifications a
WHERE a.ClientId IN (
SELECT c.Notification
FROM [dbo].ClientsNotifications a2, [dbo].Notifications c2
WHERE a2.ClientId = 1
)
but it gives me this error :
Msg 245, Level 16, State 1, Line 1
Conversion failed when converting the nvarchar value 'Notification1' to data type int.
I'm not very experienced in SQL so I'm not certain that this is even the right way (query) to fetch this data. At the end I want to get all string value notifications for user so I can show them in the view.

Use this:
select n.Notification
from Notifications n
where n.Id in
( select cn.NotificationId
from ClientNotifications cn
where cn.ClientId = 1
)
It selects all notifications where there is a matching record in ClientNotifications. There is no need for a join since you only wish the Notification field. If you do need values from that other table, use this:
select n.Notification
, cn.ClientId /* some fields from ClientNotifications */
from Notifications n
join ClientNotifications cn
on n.Id = cn.NotificationId
where cn.ClientId = 1

Your code is trying to grab the ClientID from a list of Notification messages. Try:
SELECT Notification
FROM Notifications
JOIN ClientsNotifications
ON Notifications.ClientId = ClientsNotifications.ClientId
WHERE ClientId = 1

You are selecting notifincation strings in the subquery and try to fetch the records where the client id is the same as the notification string. That doesn't only compare data of different type (hence the error), it also compares values that has nothing to do with each other.
You should use a join in the query rather than a subquery:
select
c.Notification
from
[dbo].ClientsNotifications a
inner join [dbo].Notifications c on c.ID = a.NotificationId
where
a.ClientId = 1

Your subquery will return varchar (Notification1, Notification2 or Notification3) :
SELECT c.Notification
FROM [dbo].ClientsNotifications a2, [dbo].Notifications c2
WHERE a2.ClientId = 1
I assume you just change your subquery to make it works
SELECT c.ID
FROM [dbo].ClientsNotifications a2, [dbo].Notifications c2
WHERE a2.ClientId = 1

Try this:
SELECT n.Notification -- The text of the notification record
FROM [dbo].Notifications n
INNER JOIN [dbo].ClientsNotifications cn -- join Notifications table to ClientNotifications table
ON n.Id = cn.NotificationId -- when Notification.Id matches ClientNotification.NotificationId
WHERE cn.ClientId = 1 -- where ClientId = 1
Using an inner join should be more efficient than using a subquery.

Related

Subquery SQL for link name and firstname

Hello I would like to retrieve the name and the first name in the user table thanks to the id contained in the message table (id_receive and id_send) in sql via a subquery
SELECT user.nom FROM user
WHERE user.id IN (
SELECT message.id_send, message.id_receive FROM message WHERE message.id=1
)
```
I would recommend using EXISTS, twice:
SELECT u.nom
FROM user u
WHERE EXISTS (SELECT 1 FROM message m WHERE m.id = 1 AND u.id = id_send) OR
EXISTS (SELECT 1 FROM message m WHERE m.id = 1 AND u.id = id_receive) ;
However, a JOIN might also be appropriate:
SELECT u.nom
FROM user u JOIN
message m
ON u.id IN (m.id_send, id_receive)
WHERE m.id = 1;
I suspect it isn't actually what you want but it looks like this is what you're trying to do:
SELECT user.nom FROM user
WHERE user.id IN (
SELECT message.id_send FROM message WHERE message.id=1
UNION ALL
SELECT message.id_receive FROM message WHERE message.id=1
)
The query that drives the IN should return a single column of values
Try and conceive that in works like this:
SELECT * FROM t WHERE c IN(
1
2
3
)
Not like this:
SELECT * FROM t WHERE c IN(
1 2 3
)
Nor like this:
SELECT * FROM t WHERE c IN(
1 2 3
4 5 6
)
It might help you reember that the query inside it must return a single column, but multiple rows, all of qhich are searched for a matching value c by IN
Small addition to your original query to make it working:
SELECT user.nom FROM user
WHERE user.id IN (
SELECT unnest(array[message.id_send, message.id_receive])
FROM message
WHERE message.id=1
)

How to write a query to get data count with combination of codision

I have two tables named [DrugPrescriptionEdition] and [PrescriptionDoseDetail] and now, I join that two tables using the below query and taking a result set.
select * from DrugPrescription dp where id in(
SELECT distinct dpe.template
FROM [DrugPrescriptionEdition] dpe
join PrescriptionDoseDetail pdd on pdd.prescription = dpe.id
where doseEnd_endDate is NULL and doseEnd_doseEndType =1
)
but now I want to take records only contain, (1,2) combination of 'datasource' column and prescription.id should be same.
Example : like records { prescriptionID =4 and there contain ,(1,2) }. I will not consider, only 1 ,or 2 contain records.
Need some expert help to adding this conditions to my above query and modify it .
Expected result : I need to filter out , above query result using this, new condition too.
Let me assume your records are in a single table. Here is one method:
select t.*
from t
where (t.dataSource = 1 and
exists (select 1
from t t2
where t2. prescriptionid = t.prescriptionid and
t2.dataSource = 2
)
) or
(t.dataSource = 2 and
exists (select 1
from t t2
where t2.prescriptionid = t.prescriptionid and
t2.dataSource = 2
)
);
It is unclear if any other data sources are allowed. If they are not, then add:
and
not exists (select 1
from t t3
where t3.prescriptionid = t.prescriptionid and
t3.dataSource not in (1, 2)
)

Nested SQL query searching the wrong table (postgreSQL)

I have two tables:
devices : (id (int), type(int))
devices_log : (id (int), device_id (int) (FK), data(string), date(string))
The type is a number between 1 and 10, the data column should be a number between 1 and 100 ("1", ..., "100") or "emptyX" (the X represents any character from "a" to "z")
The device which has the type 9 always has a number in the data column.
I need to update the data field for all the "type 9" devices which
have a data bigger than 50 so that ==> data = data /2.
I've started with an INNER JOIN :
select l.id
from devices_log l
inner join (select id from devices where type = 9) d on (l.device_id = d.id)
This statement returns all the logs for "type 9" devices, but when I add the where condition :
select l.id
from devices_log l
inner join (select id from devices where type = 9) d on (l.device_id = d.id)
where cast(data as INTEGER) > 50
I got this error :
ERROR: invalid input syntax for integer: "emptyG"
I've also tried so many statements that lead to the same error :
select id
from devices_log
where device_id in (select id from devices where type = 9)
and cast(data as integer) > 50
select id from
(
select id, device_id, cast (devices_log.data as integer) as int_data
from devices_log
join devices on (devices_log.device_id = devices.id
) and type = 9) ccs where ccs.int_data > 50
Any suggestions?
Thanks in advance
SQL queries describe the result set, not the specific steps being taken. I actually thought this problem didn't appear in Postgres (I've seen it in other databases). I would start with this version:
select l.id
from devices_log l inner join
devices d
on l.device_id = d.id
where d.type = 9 and cast(l.data as INTEGER) > 50 ;
If this doesn't fix the problem, then you can fix this with a case in the where:
select l.id
from devices_log l inner join
devices d
on l.device_id = d.id
where d.type = 9 and
(case when d.type = 9 then cast(l.data as INTEGER) end) > 50 ;
The case should not evaluate the then unless the condition is true.

SQL Update Skipping duplicates

Table 1 looks like the following.
ID SIZE TYPE SERIAL
1 4 W-meter1 123456
2 5 W-meter2 123456
3 4 W-meter 585858
4 4 W-Meter 398574
As you can see. Items 1 and 2 both have the same Serial Number. I have an innerjoin update statement that will update the UniqueID on these devices based on linking their serial number to the list.
What I would like to do. Is modify by hand the items with duplicate serial numbers and scripted update the ones that are unique. Im presuming I have to reference the distinct command here somewhere buy not sure.
This is my update statement as is. Pretty simple and straight forward.
update UM00400
Set um00400.umEquipmentID = tb2.MIUNo
from UM00400 tb1
inner join AA_Meters tb2 on
tb1.umSerialNumber = tb2.Old_Serial_Num
where tb1.umSerialNumber <> tb2.New_Serial_Num
;WITH CTE
AS
(
SELECT * , rn = ROW_NUMBER() OVER (PARTITION BY SERIAL ORDER BY SERIAL)
FROM UM00400
)
UPDATE CTE
SET CTE.umEquipmentID = tb2.MIUNo
inner join AA_Meters tb2
on CTE.umSerialNumber = tb2.Old_Serial_Num
where tb1.umSerialNumber <> tb2.New_Serial_Num
AND CTE.rn = 1
This will update the 1st record of multiple records with the same SERIAL.
If i understand your question correctly below query will help you out :
;WITH CTE AS
(
// getting those serial numbers which are not duplicated
SELECT umSerialNumber,COUNT(umSerialNumber) as CountOfSerialNumber
FROM UM00400
GROUP BY umSerialNumber
HAVING COUNT(umSerialNumber) = 1
)
UPDATE A SET A.umEquipmentID = C.MIUNo
FROM UM00400 A
INNER JOIN CTE B ON A.umSerialNumber = B.umSerialNumber
INNER JOIN AA_Meters C ON A.umSerialNumber = C.Old_Serial_Num

Selective update in SQL Server

I've created a junction table like this one:
http://imageshack.us/scaled/landing/822/kantotype.png
I was trying to figure out a query that could able to select some rows - based on the PokémonID - and then updating only the first or second row after the major "filtering".
For example:
Let's suppose that I would like to change the value of the TypeID from the second row containing PokémonID = 2. I cannot simply use UPDATE KantoType SET TypeID = x WHERE PokémonID = 2, because it will change both rows!
I've already tried to use subqueries containing IN,EXISTS and LIMIT, but with no success.
Its unclear what are your trying to do. However, you can UPDATE with JOIN like so:
UPDATE
SET k1.TypeID = 'somethng' -- or some value from k2
FROM KantoType k1
INNER JOIN
(
Some filtering and selecting
) k2 ON k1.PokémonID = k2.PokémonID
WHERE k1.PokémonID = 2;
Or: if you want to UPDATE only the two rows that have PokémonID = 2 you can do this:
WITH CTE
AS
(
SELECT *,
ROW_NUMBER() OVER(ORDER BY TypeID) rownum
FROM KantoType
WHERE PokemonID = 2
)
UPDATE c
SET c.TypeID = 5
FROM CTE c
WHERE c.rownum = 1;
SQL Fiddle Demo
I can suggest something like this if you just need to update a single line in your table:
UPDATE kantotype
SET
type = 2
WHERE pokemon = 2
AND NOT EXISTS (SELECT * FROM kantotype k2
WHERE kantotype.type > k2.type
AND kantotype.pokemon = k2.pokemon)
It would be easier to get the first or last item of the table if you had unique identifier field in your table.
Not sure even if you are trying to update the row with PokemenID =2 by doing a major filtering on TypeID... So just out of assumptiong (big one), you can give a try on Case
UPDATE yourtable a
LEFT JOIN youtable b on a.pokeid = b.pokeid
SET a.typeid = (CASE
WHEN a.typeid < b.typeid THEN yourupdatevalue
WHEN a.typeid > b.typeid THEN someothervalue
ELSE a.typeid END);
If you know the pokemon ID and the type id then just add both to the where clause of your query.
UPDATE KantoType
SET TypeID = x
WHERE PokémonID = 2
AND TypeID=1
If you don't know the type ID, then you need to provide more information about what you're trying to accomplish. It's not clear why you don't have this information.
Perhaps think about what is the unique identifier in your data set.