Mysql Obtaining actual value through FK when Selecting all rows - mysql

I need to select * FROM sections and get the column values for every row to fill a JTable. My problem is that my adviserId column on section table is an INT
And because I'm getting the result set of every column on every row, I cannot issue a WHERE clause. I thought of subquery but since Id is different on every row, no predetermined Id can be supplied on WHERE clause.
So If I run my stored procedure, I get just an int value for adviserId instead of the teacher's name.
I have teachers and sections table.
Teacher
id PK INT
lastName
firstName
middleName
isAdviser
status
Sections
id PK
name
adviserId FK-- REFERENCING `id` column ON teacher table
What would be the best approach? I hope you can help.
Thanks.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I've created the final stored procedure based on everyone's suggestion. (THANKS AGAIN all.)
CREATE DEFINER=`root`#`localhost` PROCEDURE `getAllSectionsInfo`()
BEGIN
SELECT
s.`name` AS `Section Name`,
s.`session` AS `Session`,
CONCAT(t.lastName,',',t.firstName,' ',t.middleName) AS Adviser,
s.yearLevel AS `Year Level`,
CONCAT(syStart,'-',syEnd) AS SchoolYear
FROM sections s
INNER JOIN
teacher t on s.adviserId = t.id;
END

Yes I also think the same, that a simple inner join will do your job. Try the below example..
create table JTable as select T.id as Tid,T.lastName,T.firstName,T.middleName,T.isAdviser,T.status,S.id as Sid,S.name,S.adviserId
from Sections as S
inner join Teachers as T on T.id = S.adviserId
You can apply left join here to make sure that you have all records of Section table either related to Teachers data or with null data.
So, now the JTable will have all the columns in that you have put on the selection list.

Below is solution for db data selection
SELECT * FROM sections s INNER JOIN teacher on s.adviserId = t.id

Related

Update Column Using ROW_Number() function. But it is failing. Could Any one suggest a solution?

I know guys, this might be a silly question, but I have not found any solution till now, so I am asking this question with all the inputs and outputs that I have done. Could anyone provide me the solution.
What I want to do is: the parcelno can have one or more invoicenumbers, I want to find how many invoice numbers does an parcel has and give it a rank. The ranking part is important because my further work is depending on this column.
I have one table named TableA. It has three columns Invoicenumber which is the unique id, ParcelNo which can be duplicate and Ranking which I want to update.
CREATE TABLE TableA
(
Invoicenumber varchar(5),
ParcelNo varchar(5),
Ranking bit,
IDate Datetime
)
INSERT INTO TableA (Invoicenumber, ParcelNo)
VALUES ('INV01', 'P0001'), ('INV02', 'P0001'),
('INV03', 'P0002'), ('INV04', 'P0002'),
('INV05', 'P0003'), ('INV06', 'P0003')
When I run the following query the output is as desired.
;WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY PARCELNO ORDER BY INVOICENUMBER) AS RWNO
FROM
TableA
)
SELECT
T.*, C.RWNO
FROM CTE C
JOIN TableA T ON T.Invoicenumber = C.Invoicenumber
The output is below:
So, I tried to update the Ranking column in Table A.
I run this query to do so:
;WITH CTE AS
(
SELECT
*,
ROW_NUMBER() OVER(PARTITION BY PARCELNO ORDER BY INVOICENUMBER) AS RWNO
FROM
TableA
)
UPDATE T
SET Ranking = C.RWNO
FROM CTE C
JOIN TableA T ON T.Invoicenumber = C.Invoicenumber
But the output is wrong. The column is not updated as expected.
Below is the output of the updated column:
Why is the Ranking column is updated incorrectly?
I want to update the column to prepare some data. This table is sample for the explanation.
I am elaborating my issue below:-
Below in the image are two tables:-
Table A and Table B has IDate column.
I want to update the IDate column in A from B. But the dates should be unique. First date should not be repeated. These date are associated with Invoicenumbers.
I think what you really want is a calculated column (called a calculated field or generated field). I'm guessing that your parcel number should point to another table that stores information about the parcels. If that's the case, then go with:
-- First approach
CREATE TABLE Parcels (
id int IDENTITY (1,1) NOT NULL,
ParcelNo varchar(5),
Description varchar(max)
-- Ranking AS (SELECT COUNT(*) FROM Invoices i WHERE i.ParcelID = id)
);
CREATE TABLE Invoices (
id int IDENTITY (1,1) NOT NULL,
InvoiceNumber varchar(5),
ParcelID int FOREIGN KEY REFERENCES Parcels(id)
);
ALTER TABLE Parcels ADD Ranking AS (SELECT COUNT(*) FROM Invoices i WHERE i.ParcelID = id);
INSERT INTO Parcels
(ParcelNo)
VALUES
('P0001'),
('P0001'),
('P0002'),
('P0003');
INSERT INTO Invoices
(InvoiceNumber, ParcelID)
VALUES
('INV01', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0001')),
('INV02', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0001')),
('INV03', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0002')),
('INV04', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0002')),
('INV05', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0003')),
('INV06', (SELECT p.id FROM Parcels p WHERE p.ParcelNo = 'P0003'));
On the other hand, if you really want all the data in a single table, then try this:
-- Second approach
CREATE TABLE TableA (
Invoicenumber varchar(5),
ParcelNo varchar(5),
Ranking AS (SELECT COUNT(*) FROM TableA a WHERE a.ParcelNo = ParcelNo)
)
Some notes:
Both of my approaches assume that by ranking, you mean that you want a count of how many invoices are in a parcel.
My first approach has a circular reference, because the Invoices table has a foreign key into the Parcels table, but the Parcels table tabulates information from the Invoices table. That's why I commented out the calculated field in the first table, then added the calculated field back in after creating both tables.
Notice that I capitalized all SQL keywords (except the types such as varchar). It's easier to read SQL if you either go with all caps or no caps for an entire query.
Notice my semicolons at the end of each logical break. Semi-colons are technically optional, but a lot of folks consider using them to be good practice.
For my first approach, I'm using a foreign key. You can read more about those here.
Because my first approach split the table into 2 tables, I needed to somehow know the id of the Parcels table when populating the Invoices table, even though the ids are given by the database (so I can't know them ahead of time). Those select statements accomplish that.
My syntax should work with SQL Server, but no necessarily with any other DBMS. That's because calculated fields are not ANSI standard.

Is there a complicated select query to solve this problem

i need to make a query on a table and inside this queryi would like to replace the value of "created_by" in the value of corsspende user "first_name"
becaus a user create another user ,so i would like return the real name of creater instead of his id
i tried to get deeper in queries typess but the are so many ,inneer join, outer ,left join ,variable ,..
i don,t know which concept is the solution [enter image description here]
You'll perform an INNER JOIN from this table back to itself:
SELECT users.*, createdby.*
FROM yourtable users
INNER JOIN yourtable createdby
ON users.created_by = createdby.id
In order to do this the each table in the FROM clause gains an alias. The first time we use it I'm calling it users and the second time I'm calling it createdby. This makes it obvious in the rest of the SQL which table is being referred to and why.
We join on the created_by of the first table to the id of the second. Essentially the second table contains the attributes of the created_by user.
You'll just have to swap the yourtable out for your actual table name and probably swap those * out with the actual fields you want from each table.
This should be handled by client side code instead of query because it causes confusion. If you really want it, you can just take first_name column value and return it as create_by like showed below:
SELECT first_name AS create_by FROM user;

SQL Query to populate table based on PK of Main Table being joined

Here is my Database structure (basic relations):
I'm attempting to formulate a one-line query that will populate the clients_ID, Job_id, tech_id, & Part_id and return back all the work orders present. Nothing more nothing less.
Thus far I've struggled to generate this Query:
SELECT cli.client_name, tech.tech_name, job.Job_Name, w.wo_id, w.time_started, w.part_id, w.job_id, w.tech_id, w.clients_id, part.Part_name
FROM work_orders as w, technicians as tech, clients as cli, job_types as job, parts_list as part
LEFT JOIN technicians as techy ON tech_id = techy.tech_name
LEFT JOIN parts_list party ON part.part_id = party.Part_Name
LEFT JOIN job_types joby ON job_id = joby.Job_Name
LEFT JOIN clients cliy ON clients_id = cliy.client_name
Apparently, once all the joining happens it does not even populate the correct foreign key values according to their reference.
[some values came out as the actual foreign key id, not even
corresponding value.]
It just goes on about 20-30 times depending on largest row of a table that I have (one of the above).
I only have two work orders created, So ideally it should return just TWO Records, and columns, and fields with correct information. What could I be doing wrong? Haven't been with MySQL too long but am learning as much as I can.
Your join conditions are wrong. Join on tech_id = tech_id, not tech_id = tech_name. Looks like you do this for all your joins, so they all need to be fixed.
I really don't follow the text of your question, so I am basing my answer solely on your query.
Edit
Replying to your comment here. You said you want to "load up" the tech name column. I assume you mean you want tech name to be part of your result set.
The SELECT part of the query is what determines the columns that are in the result set. As long as the table where the column lives is referenced in the FROM/JOIN clauses, you can SELECT any column from that table.
Think of a JOIN statement as a way to "look up" a value in one table based on a value in another table. This is a very simplified definition, but it's a good way to start thinking about it. You want tech name in your result set, so you look it up in the Technicians table, which is where it lives. However, you want to look it up by a value that you have in the Work Orders table. The key (which is actually called a foreign key) that you have in the Work Orders table that relates it to the Technicians table is the tech_id. You use the tech_id to look up the related row in the Technicians table, and by doing so can include any column in that table in your result set.

Return records from one table where Field not found in another table

I'm so lost here I don't even know how to best title my question.
I am creating a simple dating site. I want the women to be able to block the men just like all other dating sites. When this happens, I don't want the womens' profiles to be returned in a query.
Table A
Members table containing all the profile information including a member name
Table B
Blocked members table containing the woman's name and the man's name for each case in which the woman has blocked a man
So, I want something like this:
$query = Return all records from table A where sex=female and there is no record in table B containing the woman's name and the man's name
I thought I would run a query against table B to retrieve all women who have blocked me, then run a query against table A to return all females in which the woman's username is NOT contained in the results of my first query. However, I can't figure out how to do this.
If I understand your question...seems like a simple join, no? Not sure if I'm misunderstanding. Something like this perhaps:
SELECT * FROM Table1 WHERE Table1.ID NOT IN (SELECT BLOCK_ID FROM table2)
So Table1 has all ID's of the women, and Table2 has all block id's (for example) and you want what is not in that? Obviously some changes required on top of this.
If you wanted to see a list of all the female members who had blocked the current user, you would use a query like:
SELECT member.*
FROM TableA member
JOIN TableB blocked ON (member.name = blocked.user_who_blocked)
WHERE member.sex = female
AND blocked.blocked_user_name = 'Joe McCurrentUser'
;
So, if you want to see the set of users where that is not the case, you use a LEFT JOIN and look for a null id.
SELECT member.*
FROM TableA member
LEFT JOIN TableB blocked ON (member.name = blocked.user_who_blocked)
WHERE member.sex = female
AND blocked.blocked_user_name = 'Joe McCurrentUser'
AND blocked.id IS NULL
;
You can modify as you wish to use the actual columns in your tables. Make sure you have indices on both the user_who_blocked and blocked_user_name columns in that table.
Would this work?
Select * from Table A
inner join Table B on a.womans_name = B.womans_name and B.mans_name="Mans Name"
where B.womans_name IS NULL
If Table B contains a record with the matching womans_name and mans_name then the join will create one record containing all the fields in Table A and Table B but the Where clause will reject this record because the womans_name from Table B will not be null. If Table B does not contain a matching record then all those fields will be null (including B.womans_name) so the Where clause is satisfied.

A MySQL query addressing three tables: How many from A are not in B or C?

I have a problem formulating a MySQL query to do the following task, although I have seen similar queries discussed here, they are sufficiently different from this one to snooker my attempts to transpose them. The problem is (fairly) simple to state. I have three tables, 'members', 'dog_shareoffered' and 'dog_sharewanted'. Members may have zero, one or more adverts for things they want to sell or want to buy, and the details are stored in the corresponding offered or wanted table, together with the id of the member who placed the ad. The column 'id' is unique to the member, and common to all three tables. The query I want is to ask how many members have NOT placed an ad in either table.
I have tried several ways of asking this. The closest I can get is a query that doesn't crash! (I am not a MySQL expert by any means). The following I have put together from what I gleaned from other examples, but it returns zero rows, where I know the result should be greater than zero.
SELECT id
FROM members
WHERE id IN (SELECT id
FROM dog_sharewanted
WHERE id IS NULL)
AND id IN (SELECT id
FROM dog_shareoffered
WHERE id IS NULL)
THis query looks pleasingly simple to understand, unlike the 'JOIN's' I've seen but I am guessing that maybe I need some sort of Join, but how would that look in this case?
If you want no ads in either table, then the sort of query you are after is:
SELECT id
FROM members
WHERE id NOT IN ( any id from any other table )
To select ids from other tables:
SELECT id
FROM <othertable>
Hence:
SELECT id
FROM members
WHERE id NOT IN (SELECT id FROM dog_shareoffered)
AND id NOT IN (SELECT id FROM dog_sharewanted)
I added the 'SELECT DISTINCT' because one member may put in many ads, but there's only one id. I used to have a SELECT DISTINCT in the subqueries above but as comments below mention, this is not necessary.
If you wanted to avoid a sub-query (a possible performance increase, depending..) you could use some LEFT JOINs:
SELECT members.id
FROM members
LEFT JOIN dog_shareoffered
ON dog_shareoffered.id = members.id
LEFT JOIN dog_sharewanted
ON dog_sharewanted.id = members.id
WHERE dog_shareoffered.id IS NULL
AND dog_sharewanted.id IS NULL
Why this works:
It takes the table members and joins it to the other two tables on the id column.
The LEFT JOIN means that if a member exists in the members table but not the table we're joining to (e.g. dog_shareoffered), then the corresponding dog_shareoffered columns will have NULL in them.
So, the WHERE condition picks out rows where there's a NULL id in both dog_shareoffered and dog_sharewanted, meaning we've found ids in members with no corresponding id in the other two tables.