running queries on more than one table - sql

I'm trying to make a query in two tables:
SIMPLE_PERSON with 3 fields (name, grid and Social Security Card)
INDIVIDUAL_AGGREGATE with 4 fields: grid(PK), type( D(Driver) or C(client)), code, simple_person(foreign key of simple_person))
When I register some person, I have to save they on the SIMPLE_PERSON and set the type of aggregate that they are ( Driver or Client). And cannot have two equal social security card numbers.
With AJAX, I throw a checker that returns an alert box if the SSC is registered, but my SQL query doesn't work. I need to making a query that returns to me if a Social Security Card is already registered. I'm trying to use EXISTS, but I haven't had much success:
SELECT simple_person.name
FROM simple_person
WHERE SSC = 'SSC_NUMBER'
AND EXISTS (SELECT individual_aggregate.code FROM individual_aggregate
WHERE code = 'xx'
AND individual_aggregate.type = 'D');
Somebody can help me to make this query work?

did you wanted to check if there is a person that registered on a some Social security number?
if yes what i did is join between the two tables
and return the rows that equal to a specific social security number.
you can add to the WHERE statement (AND IA.code = 'XX' AND IA.Type = 'D')
SELECT SP.Name
FROM simple_person AS SP
INNER JOIN individual_aggregate AS IA ON SP.grid = IA.grid
WHERE SP.SSC = {someNumber}
helped you?

Your subquery in the EXISTS clause isn't actually hitting a table, view or other.

Your sub-select is missing the FROM clause.
SELECT
individual_aggregate.code
FROM
individual_aggregate
WHERE
code = 'xx'
AND individual_aggregate.type = 'D'
Regards
Sigersted

Related

Selecting rows from Parent Table only if multiple rows in Child Table match

Im building a code that learns tic tac toe, by saving info in a database.
I have two tables, Games(ID,Winner) and Turns(ID,Turn,GameID,Place,Shape).
I want to find parent by multiple child infos.
For Example:
SELECT GameID FROM Turns WHERE
GameID IN (WHEN Turn = 1 THEN Place = 1) AND GameID IN (WHEN Turn = 2 THEN Place = 4);
Is something like this possible?
Im using ms-access.
Turm - Game turn GameID - Game ID Place - Place on matrix
1=top right, 9=bottom left Shape - X or circle
Thanks in advance
This very simple query will do the trick in a single scan, and doesn't require you to violate First Normal Form by storing multiple values in a string (shudder).
SELECT T.GameID
FROM Turns AS T
WHERE
(T.Turn = 1 AND T.Place = 1)
OR (T.Turn = 2 AND T.Place = 4)
GROUP BY T.GameID
HAVING Count(*) = 2;
There is no need to join to determine this information, as is suggested by other answers.
Please use proper database design principles in your database, and don't violate First Normal Form by storing multiple values together in a single string!
The general solution to your problem can be accomplished by using a sub-query that contains a self-join between two instances of the Turns table:
SELECT * FROM Games
WHERE GameID IN
(
SELECT Turns1.GameID
FROM Turns AS Turns1
INNER JOIN Turns AS Turns2
ON Turns1.GameID = Turns2.GameID
WHERE (
(Turns1.Turn=1 AND Turns1.Place = 1)
AND
(Turns2.Turn=2 AND Turns2.Place = 4))
);
The Self Join between Turns (aliased Turns1 and Turns2) is key, because if you just try to apply both sets of conditions at once like this:
WHERE (
(Turns.Turn=1 AND Turns.Place = 1)
AND
(Turns.Turn=2 AND Turns.Place = 4))
you will never get any rows back. This is because in your table there is no way for an individual row to satisfy both conditions at the same time.
My experience using Access is that to do a complex query like this you have to use the SQL View and type the query in on your own, rather than use the Query Designer. It may be possible to do in the Designer, but it's always been far easier for me to write the code myself.
select GameID from Games g where exists (select * from turns t where
t.gameid = g.gameId and ((turn =1 and place = 1) or (turn =2 and place =5)))
This will select all the games that have atleast one turn with the coresponding criteria.
More info on exist:
http://www.techonthenet.com/sql/exists.php
I bypassed this problem by adding a column which holds the turns as a string example : "154728" and i search for it instead. I think this solution is also less demanding on the database

Need to return multiple entries from a single field in One Table

So Here is the problem I have a requirement where I need a customer type to equal two different things.
To Cover the requirement I don't need the customer type to equal Client, or Non client but equal Client, and Non_Client. Each Customer_No can have multiple Customer Types
Here is an example of what I have worked on so far. If you know a better way of optimizing this as well as solving the problem please let me know.
The out put should look like this
CustomerID CustomerType CustomerType
--------------------------------------
2345 Client NonClient
Select TB1.Customer_ID, IB1.Customer_Type, AS Non_client IB1.Customer_Type AS Client
From Client TB1, Client_ReF XB1, Client_Instr IB1, Client_XREC FB1
Where XB1.Client_NO = TB1.Client_NO
AND FB1.Client_ACCT = TB1.ACCT
AND XB1.Client_Instruct_NO = IB1.Client_Instruct_NO
AND FB1.Customer_ID= TB1. Client_NO
AND IB1.Client = 'Client'
AND IB1.Non_Client = 'NonClient'
I have omitted a few other filters that I felt were unnecessary. This also may not make sense, but I tried to change up the names of stuff as to keep myself in compliance.
First a small syntactic error:
You mustn't have a comma before the "AS Non_client "
Then what you are trying to do is make 1 value equal 2 different things for the same column which can never be true:
IB1.Customer_Type for 1 record can never be equal to "Client" and "NonClient" simultaneously.
The key here is that 1 customer can have multiple records and the records can differ in the customer_type. So to use that we need to join those records together which is easy since they share a Customer_ID:
Select TB1.Customer_ID,
IB1.Customer_Type AS Client,
IB2.Customer_Type AS Non_client
From Client TB1,
Client_ReF XB1,
Client_Instr IB1,
Client_Instr IB2,
Client_XREC FB1
Where XB1.Client_NO = TB1.Client_NO
AND FB1.Client_ACCT = TB1.ACCT
AND XB1.Client_Instruct_NO = IB1.Client_Instruct_NO
AND FB1.Customer_ID= TB1.Client_NO
AND IB1.Client = 'Client'
AND XB1.Client_Instruct_NO = IB2.Client_Instruct_NO
AND IB2.Non_Client = 'NonClient';
The above may not actually work due to me not fully understanding your data and structures but should put you on the right path. Particularly around the join of IB2 with XB1, you might have to join IB2 with all the same tables as IB1.
A better way than that however, and i'll leave you to research it, is using the EXISTS statement. The difference is that the above will join all records for the same customer together whereas EXISTS will just be satisfied if there's at least 1 instance of a "NonClient" record.

ORA-00904 Invalid Identifier - Update Statement With Two Tables

I'm working with PeopleSoft Campus Solutions, and we need to update about 22,000 rows of data. This is data between the tables of ACAD_PLAN_VW and ACAD_PROG. Students are listed on both, so their IDs match between the two.
Basically what we are trying to do is say that when the ID, academic career, student career number, effective sequence, and effective date match, AND where the academic plan (their degree, as stored on the ACAD_PLAN_VW) is a specific value, update the ACAD_PROG on the ACAD_PROG table to X value.
I tried to do some very interesting combinations of FROM statements, constantly getting errors. After some researching, I found out that SQLTools doesn't really like FROM statements within UPDATE statements, so I rewrote it to just make the connections manually. I'm assuming I'm doing this right, unless I need to reword it.
The statement I have is:
UPDATE PS_ACAD_PROG SET PS_ACAD_PROG.ACAD_PROG = 'UGDS'
WHERE PS_ACAD_PLAN_VW.EMPLID = PS_ACAD_PROG.EMPLID
AND PS_ACAD_PLAN_VW.ACAD_CAREER = PS_ACAD_PROG.ACAD_CAREER
AND PS_ACAD_PLAN_VW.STDNT_CAR_NBR = PS_ACAD_PROG.STDNT_CAR_NBR
AND PS_ACAD_PLAN_VW.EFFSEQ = PS_ACAD_PROG.EFFSEQ
AND PS_ACAD_PLAN_VW.EFFDT = PS_ACAD_PROG.EFFDT
AND PS_ACAD_PLAN_VW.ACAD_PLAN = 'DSTDS'
Theoretically, I would assume that this would update any student who has those connections. However, the error that I'm currently getting is as follows:
ORA-00904: "PS_ACAD_PLAN_VW"."ACAD_PLAN": invalid identifier
I have, as of yet, been unable to figure out the issue. I do have the correct access to view and update those fields, and the field does indeed exist.
Oracle doesn't know it should use the PS_ACAD_PLAN_VW table. Somehow you should reference it.
For example can you try this way?
UPDATE (
select
PS_ACAD_PROG.ACAD_PROG,
PS_ACAD_PLAN_VW.ACAD_PLAN
from
PS_ACAD_PROG,
PS_ACAD_PLAN_VW
where
PS_ACAD_PLAN_VW.EMPLID = PS_ACAD_PROG.EMPLID
AND PS_ACAD_PLAN_VW.ACAD_CAREER = PS_ACAD_PROG.ACAD_CAREER
AND PS_ACAD_PLAN_VW.STDNT_CAR_NBR = PS_ACAD_PROG.STDNT_CAR_NBR
AND PS_ACAD_PLAN_VW.EFFSEQ = PS_ACAD_PROG.EFFSEQ
AND PS_ACAD_PLAN_VW.EFFDT = PS_ACAD_PROG.EFFDT
)
SET
ACAD_PROG = 'UGDS'
WHERE
ACAD_PLAN = 'DSTDS'
Try to use the table which is not getting identified,by keeping in where clause so that you can use the select statement.That will help identifying the tables.
The following implementation should work:
UPDATE PS_ACAD_PROG
SET ACAD_PROG = 'UGDS'
WHERE ROWID IN(SELECT PROG.ROWID
FROM PS_ACAD_PROG PROG
, PS_ACAD_PLAN_VW PLAN
WHERE PLAN.EMPLID = PROG.EMPLID
AND PLAN.ACAD_CAREER = PROG.ACAD_CAREER
AND PLAN.STDNT_CAR_NBR = PROG.STDNT_CAR_NBR
AND PLAN.EFFSEQ = PROG.EFFSEQ
AND PLAN.EFFDT = PROG.EFFDT
AND PLAN.ACAD_PLAN = 'DSTDS');

SQL Inner Join and Grouping

It's been a while since I've done SQL, but I have a rather pressing issue.
My db-layout is as following:
Now, starting from a Users.ID, I want to get all the Rounds the user has played. The user could be Hosts.HostID, Host.GuestID, or even both. Where he is both, it should not show op in the results.
The results I need from the Query are the Hosts.Name and all the fields of Rounds. In general what I want to do is display a list of all the Hosts (actually these are the Games) in which the user has participated, as a Host or as a Guest, along with perhaps a total score. When clicking on this, some dropdown will appear showing the individual round scores, words, ...
Now I was wondering whether this was possible in a single query. Of course I could do a query getting all the Hosts and then per Host a query for each Round, but that doesn't seem that performant. This is what I've come up with so far:
SELECT Rounds.ID, Rounds.GameID, Rounds.Round, Rounds.Score, Rounds.Word
, Hosts.ID, Hosts.HostID, Hosts.GuestID
FROM Rounds INNER JOIN Hosts
ON Rounds.GameID = Hosts.ID
INNER JOIN Users
ON Hosts.hostID = Users.ID
WHERE Users.ID = 5
The issue is however that it doesn't filter out where the user is both host AND guest, and I can't seem to Group it by Hosts.ID either.
Add Hosts.hostID <> Hosts.guestID to the where clause.
If you are using SQL Server 2005 or later version, you could modify your present query like this:
SELECT Rounds.ID, Rounds.GameID, Rounds.Round, Rounds.Score, Rounds.Word
, Hosts.ID, Hosts.HostID, Hosts.GuestID
FROM Rounds INNER JOIN Hosts
ON Rounds.GameID = Hosts.ID
CROSS APPLY
(
SELECT Hosts.HostID
UNION
SELECT Hosts.GuestID
) AS u (UserID)
WHERE u.UserID = 5
;
The CROSS APPLY clause would produce either one or two rows, depending on whether HostID and GuestID are equal. In either event, the WHERE condition would ultimately leave at most one. Thus, the above query would give you only the games (with all their rounds) where the specified user participated.
And from that query you could easily get to something like this:
SELECT Hosts.ID,
TotalScore = SUM(Rounds.Score)
FROM
...
GROUP BY
Hosts.ID
;

SQL outer join in combination with MAX function in right table

I have an SQL question based on below table structure.
Database is currently in MS Access, with plans to migrate to SQL Server. Query should work in both DBMS'es.
I want to get devName and the latest dswSW_Version, based on dswTimestamp, for the device in question. If no SW history exists, I want to just return the devName.
The closest I could get was:
SELECT dev.devname, dsw1.dswsw_version
FROM device_sw_history AS dsw1 RIGHT JOIN device AS dev
ON dsw1.dswdevid = dev.devid
WHERE dsw1.dswtimestamp = (SELECT MAX(dswtimestamp) FROM device_sw_history AS dsw2 WHERE dsw1.dswdevid = dsw2.dswdevid)
AND devid = #devid
But nothing is returned for devid = 2, due to MAX returning null. I want to return Apple, null.
Is there a way to construct this statement without using a UNION and still return devname even if no SW history exists ?
Device:
devid devname
1 Samsung
2 Apple
Device_SW_History:
dswid dswdevid dswtimestamp dswsw_version
1 1 5/dec/13 One
2 1 6/dec/13 Two
Thank you !
Just put your condition in the on clause:
SELECT dev.devname, dsw1.dswsw_version
FROM device_sw_history AS dsw1 RIGHT JOIN device AS dev
ON dsw1.dswdevid = dev.devid
AND dsw1.dswtimestamp = (SELECT MAX(dswtimestamp) FROM device_sw_history AS dsw2 WHERE dsw1.dswdevid = dsw2.dswdevid)
WHERE devid = #devid
For inner joins the on and where clauses are identical, and putting a condition in one or the other is merely a question of style and readability. Outer joins introduce a difference between on and where, the on clause only applies to one table, while the where clause applies to their combination.
On SQL Server, a simple subquery should do the trick:
SELECT
devname,
(SELECT TOP 1 dswsw_version FROM device_sw_history WHERE dswdevid = devid
ORDER BY dswtimestamp DESC)
FROM device
This will return all the device names from device, even those that does not have an entry in device_sw_history.