I Have two Tables tblSiteVisits and tblConformedList and Colums as Below
tblSiteVisits
Name | EmailAddress
tblConformedList
Name | EmailAddress | ContactNo | Location | Conform_Status
The First Table Contains Name and EmailAddress of all those who have SiteVisits
Now in the Second table Conform_Status will be set either to 1 or 0 based on the client availability at point of time for site visit.
If not I will fill the ContactNo and Location and just update the table with Conform_Status = 0.
Now what i want is I want to take the Name and EmailAddress of people from table tblSiteVisits and tblConformedList by relating the EmailAddress in join and the rows in tblConformedList whose Conform_Status is 0.
That is List of people who have given ContactNo and Location for update but not given the Conform_Status.
Thanks in Advance
May be it helps you.
select t1.* from tblSiteVisits t1 inner join tblConformedList t2 on
t1.EmailAddress=t2.EmailAddress where t2.Conform_Status=0
Try it and share your feedback.
Sorry, if you only need the rows where Conform_Status is 0, you don't need a LEFT JOIN, you need an INNER JOIN.
SELECT v.*
FROM tblSiteVisits v
JOIN tblConformedList c
ON v.EmailAddress = c.EmailAddress
WHERE c.Conform_Status=0
Because the c.Conform_Status=0 will filter out all rows where it is not 0, including the rows with NULL, rows in tblSiteVisits that have no correspondent row in tblConformedList will be filtered anyway - hence just use an INNER JOIN.
If you want an entry for all rows, then you can left-join, put the where-clause in the on-clause or add a OR Conform_Status IS NULL in your where clause.
SELECT v.*
FROM tblSiteVisits v
LEFT JOIN tblConformedList c
ON v.EmailAddress = c.EmailAddress
AND c.Conform_Status=0
This will display each row in tblSiteVisits, and if possible, the data for tblConformedList, but only when Conform_Status is actually 0.
Related
I have a form with radio buttons which stores the value (which is the ID) in my MySQL database along with the necessary information from the user.
INSERT INTO table (user_id, name, address, prefer_id) VALUES ('', ?, ?, ?);
So when I try to fetch the data, I use LEFT JOIN, to get the necessary description from table2:
SELECT a.name, a.address, b.prefer_desc FROM table a
LEFT JOIN table2 b ON a.prefer_id = b.prefer_id
WHERE a.user_id = ?
But I have created an other option, in case the option the user prefers is not in the list. A textbox will appear when the user selects Other in the list of radio buttons so they can type-in freely their preferred data. Check this fiddle to see an example.
The first logic that I've thinked of is to create a separate table which stores the typed-in data of the user.
other_tb:
other_id | user_id | typed_in |
----------+---------+----------+
1 | 1 | cake |
2 | 3 | pizza |
So when I fetch the data, I use php's if() condition if the prefer_id is 4 (or other), and if it does, I will use another SELECT query to get the other data in other_tb table.
SELECT typed_in FROM other_tb WHERE user_id = ?
Is there a way to do all of this in a single query?
OR
Is this the best option, or is there a right or better way in this kind of situation?
try this
SELECT
a.name,
a.address,
IF(a.prefer_id=4,(SELECT typed_in FROM other_tb WHERE user_id = a.user_id),b.prefer_desc) as prefer_desc
FROM table a
LEFT JOIN table2 b
ON a.prefer_id = b.prefer_id
WHERE a.user_id = ?
If you are using the second table as you described, and you want to keep the same format of the output and assuming the records in other_tb are unique for each user_id, you could use something like this:
SELECT a.name, a.address,
CASE
WHERE a.prefer_id = 4 THEN c.typed_in
ELSE b.prefer_desc
END CASE AS prefer_desc
FROM table a
LEFT JOIN table2 b ON a.prefer_id = b.prefer_id
LEFT JOIN other_tb c ON a.user_id = c.user_id
WHERE a.user_id = ?
I think this can also be written as:
SELECT a.name, a.address,
CASE a.prefer_id
WHERE 4 THEN c.typed_in
ELSE b.prefer_desc
END CASE AS prefer_desc
FROM table a
LEFT JOIN table2 b ON a.prefer_id = b.prefer_id
LEFT JOIN other_tb c ON a.user_id = c.user_id
WHERE a.user_id = ?
There are two approaches that I was able to practice depending on the situation:
Allow users to add more options so that their answer is still indexed to table2. So when fetching data, you may still use LEFT JOIN to get the user's preferred option without any other condition. But this method will allow users to see the options that was added by other users.
If the options are "fixed" and only the administrator is allowed to add options to table2, have another column to table1, which stores the other answer of the user (let say other_option column). This method allows the user to still freely state their option without adding options to table2.
Here is table1:
+---------+------+---------+-----------+--------------+
| user_id | name | address | prefer_id | other_option |
+---------+------+---------+-----------+--------------+
What I do is I put 0 to prefer_id if the user prefers to answer other_option. So your program expects that if the prefer_id is 0, you have an input in other_option.
This question already has answers here:
How to resolve ambiguous column names when retrieving results?
(11 answers)
Closed 2 years ago.
I have some big tables which I need to combine into a single very large table, to form a single-page data export for a statistical package.
This is easy with INNER JOIN but the some of the tables have the same column names and these are being overwritten by each other when I fetch them as an array in PHP.
There are 4 tables being joined with 30-200 columns in each so there are far too many field names to manually include in the query with aliases, as would be the norm in this situation.
Here's the query:
SELECT * FROM logs
INNER JOIN logdetail ON logdetail.logID = logs.id
INNER JOIN clients ON clients.id = logs.clientID
INNER JOIN records ON records.id = logdetail.id
WHERE logs.userID=1
Is there any way around this? I don't actually mind what the column names are as long as I have the data so if I could prepend the table name to each field, that would do the trick.
I would create a view, your view would be comprised of your long query with aliases
Here is an example taken from the manual
mysql> CREATE TABLE t (qty INT, price INT);
mysql> INSERT INTO t VALUES(3, 50);
mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql> SELECT * FROM v;
+------+-------+-------+
| qty | price | value |
+------+-------+-------+
| 3 | 50 | 150 |
+------+-------+-------+
This has always worked for me, unless you have one to many or some other relationship among these tables, which will duplicate records.
SELECT * FROM logs l
INNER JOIN logdetail ld ON ld.logID = l.id
INNER JOIN clients c ON c.id = l.clientID
INNER JOIN records r ON r.id = ld.id
WHERE l.userID=1
As andrew says you can also use a View to get this thing working which is much cooler.
I found a solution for this. Simply, fetch each duplicate column a second time, this time using an alias. This way, the overwritten values are selected again and aliased:
SELECT * FROM logs,
clients.name as clientName,
logs.name as logName,
etc...
INNER JOIN logdetail ON logdetail.logID = logs.id
INNER JOIN clients ON clients.id = logs.clientID
INNER JOIN records ON records.id = logdetail.id
WHERE logs.userID=1
Note: There is no need to do this for the final instance of the duplicate, because this column will not have been overwritten. So, in the example above, there is no need to include a line like records.name as recordName because, since there are no columns after it which have the same name, the record.name field was never overwritten and is already available in the name column.
SELECT * FROM conversation_1
LEFT JOIN conversation_2
ON conversation_1.c_id = conversation_2.c_id
LEFT JOIN user
ON conversation_2.user_id = user.user_id
LEFT JOIN message
ON conversation_1.c_id = message.c_id
WHERE conversation_1.user_id=1
GROUP BY message.c_id
conversation_1 conversation_2
c_id user_id c_id user_id
1 1 1 2
2 1 2 3
3 2
I have a message DB build in Mysql
I make 4 tables user, conversation_1, conversation_2, message
when user try to open his message box, it will fetch out all conversations(conversation_1)
than join to user conversation_2 and use conversation_2 to find out which user
than join to the message.
c_id user_id user_name message
1 2 Alex Hi user_1, this is user_2
2 3 John hi user_3, user_2 don't talk to me
it works fine, however I want to display the message from last row GROUP BY
currently it display the 1st row in this group.
ps.conversation_1.c_id is auto increment and the c_id will insert to conversation_2 who has join this conversation
select * from (SELECT * FROM conversation_1
LEFT JOIN conversation_2
ON conversation_1.c_id = conversation_2.c_id
LEFT JOIN user
ON conversation_2.user_id = user.user_id
LEFT JOIN message
ON conversation_1.c_id = message.c_id
WHERE conversation_1.user_id=1
order by conversation_1.c_id desc) finalData
GROUP BY message.c_id
Beware that, as documented under MySQL Extensions to GROUP BY:
MySQL extends the use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. You can use this feature to get better performance by avoiding unnecessary column sorting and grouping. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are indeterminate. Furthermore, the selection of values from each group cannot be influenced by adding an ORDER BY clause. Sorting of the result set occurs after values have been chosen, and ORDER BY does not affect which values within each group the server chooses.
This is what is happening to select the message (and potentially other columns) in your existing query.
Instead, you want the groupwise maximum:
SELECT messages.* FROM messages NATURAL JOIN (
SELECT c_id, MAX(m_id) m_id FROM messages GROUP BY c_id
) t
i have an Table with Users and an Table with events that is related to the id from the Users Table. In each Event you can make points and i want to get the total points from an specific User.
It looks like this:
Users
+----+----------+
| id | username |
+----+----------+
Events
+----------+---------+--------+
| event_id | user_id | points |
+----------+---------+--------+
// The event_id is related to an Event Table with specific data about the Event. but that not relevant.
The best could be to get the data from the user and the total points that he got in one query.
Thanks and Greetings,
Mottenmann
"..to get the data from the user and the total points that he got in one query."
You need to join both tables first so you can manipulate the data. The query below uses INNER JOIN which only includes users on the result list if it has atleast one matching record on the Events. If you want to get all users even without a single matching record on the other table, use LEFT JOIN instead.
SELECT a.ID, a.username, SUM(b.points) totalPoints
FROM Users a
INNER JOIN Events b
ON a.ID = b.user_ID
GROUP BY a.ID, a.username
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins
"In each Event you can make points and i want to get the total points
from a specific User."
You could do something like this:
select sum(e.points) as points from users u
left join events e ON (u.id = e.user_id)
WHERE u.id = {$id}
where {$id} is the id of user.
I have been trying to understand joins for a while now, I've noticed quite a few examples showing how to retrieve a value based on a two-table query using a left / inner join. I will try to draw out my example for you all, hopefully it will aid in the explanation of my question.
Table 1:
project_id | project_name
1 super-project
Table 2:
project_id | course_id ---> project_id and course_id are foreign keys here.
1 3
Table 3:
course_id | course_name ---> course_id is a primary key here
3 | Writing 101
My Goal:
I would like to be able to return "Writing 101" by using the project_id. So, if I know the project_id is 1, I would query the db to find that the course_id associated with the current project is 3. I would then use the course_id of 3 to query table 3 and find that the related course_name is writing 101.
Is there a way to do this in a single query using join of some sort?
select course_name from Table3
inner join Table2
on Table2.course_id = Table3.course_id
where Table2.project_id = 1
Notice there is only 1 join needed!
Also note that if the project_id = 1 is present in more than one course all of those courses will appear.
Can you explain why only one join is needed as opposed to the answer below which requires two joins?
The other answer does not require two joins. As the project_id is present in the "middle" table there is no need to look for it in Table1. Now, if you require the name of the project (which is not the case because you didn't mention that in the question) then you would have to join the Table1
Here you go:
SELECT c.course_name
FROM Table3 c
INNER JOIN Table2 pc ON pc.course_id = c.course_id
INNER JOIN Table1 p ON p.project_id = pc.project_id
WHERE project_id = 1