I'm trying to get a SQL result where I want to join some fields to users (from a Drupal database). My query looks like this:
SELECT * FROM users LEFT OUTER JOIN field_data_field_wekelijkse_newsletter ON users.uid = field_data_field_wekelijkse_newsletter.entity_id
LEFT OUTER JOIN field_data_field_woonplaats ON users.uid = field_data_field_woonplaats.entity_id
LEFT OUTER JOIN field_data_field_naam ON users.uid = field_data_field_naam.entity_id
I have two problems:
I get double results (usernames)
The values for "field_data_field_wekelijkse_newsletter" are different within the double results.
Can someone help me write a good query?
Without knowing too much about your data model, and only going off the naming of the columns, it is possible that your results are not duplicates after all. If users can subscribe to more than one newsletter, than perhaps that is what is happening. You are returning all of the fields from every table that you JOIN on. If you provide more information such as schema definitions, column names, etcetera, I can give a much more precise answer.
In addition, I can offer you a few styling tips in regards to writing SQL!
Use newlines and tabs, write your queries for the developer coming in behind you! Readable queriers are the best (and usually bug free) queries.
Use aliases. Typically, I treat aliases very similar to variable names: I keep them meaningful and short. If you cannot create a meaningful, short alias for the table, then use the table's initials (for table names such as field_data_field_woonplaats, it is difficult to create a simple alias! Consider renaming)
Nomenclature is everything! Name your tables, columns, views, indexes, triggers, keys, everything, simply so that you (and other developers) can remember them easily and are able to grasp and fully understand what kind of object they represent (the data they hold).
Use semicolons to terminate statements.
SELECT *
FROM users u
LEFT OUTER JOIN field_data_field_wekelijkse_newsletter fdfwn
ON u.uid = fdfwn.entity_id
LEFT OUTER JOIN field_data_field_woonplaats fdfw
ON u.uid = fdfwn.entity_id
LEFT OUTER JOIN field_data_field_naam fdfn
ON u.uid = fdfn.entity_id;
Related
I have a scenario where I have the following tables:
Inventories
delivery_items
deliveries
I seek a query where, having the inventory id, I get the delivery_item(fk_inventory),
which then I get the delivery from the (fk_delivery).
Manually, I go to the delivery_items table, then I search for the fk_inventory that matches the id from the inventory that I'm looking for,
then I get the fk_delivery, and get the delivery.
But I need to run a report on 15k+ items.
How to write a query where from a list of inventory ids I can get to the delivery following the relationship that I mentioned above?
There are many sites on writing SQL queries, differentiating between a normal (inner) join vs outer join, left join, right join, subqueries, etc. What you are looking to do is probably best (due to all inventory items in question) is simple joins.
Try to think of it this way, and maybe do it this way. Have a sheet of paper, one representing each table and write the columns on it.
Now, visually looking at the available tables, put them next to each other based on how they are related. Note the column in table A that is the foreign key to the next table. Then again, from the second to the third.
Once you have this done (or even if just mentally), you can SEE how they are related. This is the basis of the FROM clause
select *
from
YourFirstTable yft
JOIN YourSecondTable yst
on yft.WhateverKey = yst.MatchingKeyColumn
JOIN YourThirdTable ytt
on yst.KeyToThirdTable = ytt.KeyInThisTable
Now that you have all your relationships established, you can always declare the individual columns you want from those respective tables. Easier to use with the aliases such as I provided here via yft, yst, ytt representing the first, second and third tables. Use aliases appropriate to your tables such as i=inventories, di = delivery_items, d = deliveries.
Then add whatever FILTERING conditions you want. If the condition is based on the FIRST Table such as yft above, that would go into the WHERE clause such as
where
yft.SomeColumn = 'blah'
If the filtering criteria is specific to your second or third table, just add that to the JOIN / ON condition so it stays with the table and you know contextually it is associated HERE. It makes it easier when you are getting into LEFT JOINs.
from
YourFirstTable yft
JOIN YourSecondTable yst
on yft.WhateverKey = yst.MatchingKeyColumn
AND yst.SecondTableColumn = 'someOtherValue'
AND yst.SomeOtherColumn = 'somethingElse'
So now, the engine can go through all inventory items, to the corresponding details, to the actual deliveries without having to do individual searches each time which would be painful to trace / run / and performance.
SELECT
ost_form_entry_values.value as ost_form_entry_values__value
FROM
ost_ticket AS t
LEFT JOIN ost_form_entry
ON t.ticket_id = ost_form_entry.object_id
LEFT JOIN ost_form_entry_values
ON ost_form_entry_values.entry_id = ost_form_entry.id
WHERE ost_form_entry_values.field_id = 20
In that case, the only purpose of ost_form_entry is to connect to ost_form_entry_values for the value I'm looking for.
Is there different/better way to do that so that I'm not joining in a table that I'm not referencing in the final output?
Without changing the data model the answer is no. It's a normal thing to follow relations between tables to get the data you need.
If there's 1:1 relationship between ost_form_entry and ost_form_entry_values then you could put the object_id into the values table (that would avoid the JOIN), but I suspect that you have the so called Entity–attribute–value model which is by the way not the best way to keep unstructured data in SQL.
MySQL 5.7+ supports JSON format for example, so you could investigate that for the same purpose you are using your values table (and get rid of that table). Though, it would require the application to be adjusted in (probably) many places and if your MySQL version is older, an upgrade of the database.
I tried to find if there are any answered but couldn't seem to find any. I'm trying to join together four tables but one of the joins is not on the table that the other two joins are from, I've successfully joined three of the table I'm just not sure of syntax for joining the third.
SELECT * FROM
nc_booking
INNER JOIN
nc_customer ON nc_booking.c_id = nc_customer.id
INNER JOIN
nc_propertys ON nc_booking.p_id = nc_propertys.id
How would i now join nc_propertys to another table nc_owner?
Building on the code from #GordonLinoff, to add your extra table you need to do something like:
SELECT *
FROM nc_booking b INNER JOIN
nc_customer c
ON b.c_id = c.id INNER JOIN
nc_propertys p
ON b.p_id = p.id INNER JOIN
nc_owner o
ON o.id = p.o_id;
You haven't shared the column names we need to use to connect the extra table, so the last line might not be right. A few things to note ...
(1) The SELECT * is not ideal. If you only need particular columns here, list them. I've stuck with your * because I don't know what you want from the tables. Where a column with the same name exists in each table, you'll have "fully qualify" the field name as follows ...
SELECT c.id as customer_id,
-- more field can go here, with a comma after each
...
Several of the joined tables have an id field, so the c. is necessary to tell the database which one we want. Notice that as with the tables, we can also give the fields an 'alias', which in this case is 'customer_id'. This can be very helpful for presentation, and is often essential when using the output from a query as part of a larger piece of code.
(2) Since all the joins are INNER JOINS it makes little (if any) difference what order the tables are listed as long as the connections between them remain the same.
(3) For MySQL, it technically shouldn't matter whether you have lots of new-lines or none at all. SQL is designed to ignore "white space" (except within data). What matters is simply laying out your code so it is easy to read ... especially for other users who later might need to figure out what you were doing (although in my experience also for you, when you return to a piece of code several years later and can't remember it at all).
(4) In each ON clause it doesn't actually matter whether you wright say a = b or b = a. That's because you aren't setting one to equal the other, you are requiring that they already be equal so it amounts to the same thing either way.
My advice to a SQL beginner would be when you are writing a SELECT query (which only reads and doesn't change any data): if you aren't too sure then write some code and set it to run. If it's completely invalid, your software should give you some idea of what is wrong and no harm will be done. If it's valid but wrong, the very worst that can happen is that you put some unnecessary load on your database server ... if it takes a long time to run and you weren't expecting it to, then you should be able to cancel the query. As long as you have some idea of what you expect the results to look like, and roughly how many rows to expect, you won't go too far wrong. If you get completely stuck come back here to Stack Overflow.
Things get a bit different if you are writing code which DELETEs or UPDATEs data. Then you want to know exactly what you're up to. Normally you can write a closely related SELECT statement first to make sure you're going to be making all and only the changes you were expecting. It's also best to make sure you've got a way to undo your changes should the worst happen. Backups are obviously good, and you can often create your own backup copy of a table before you make any alterations. You don't necessarily need to rely on backup software or your in house IT guys for that ... in my experience they don't like databases anyway.
Also there are some great books out there. For a beginner, I'd recommend anything by Ben Forta, including his SQL in 10 Minutes (that's a per chapter figure), or his MySQL Crash Course (the latter is a little old though, so won't have anything on the more recently added features of MySQL).
Your syntax looks okay. I am providing an answer because you really should learn to use table aliases. They make a query easier to write and to read:
SELECT *
FROM nc_booking b INNER JOIN
nc_customer c
ON b.c_id = c.id INNER JOIN
nc_propertys p
ON b.p_id = p.id;
i have a MySQL statement which works - i can get the records requested - movies.* & groups.name.
$stmt= $mysqli->query("SELECT DISTINCT ebooks.*, groups.name FROM ebooks
INNER JOIN ebooks_groups ON ebooks.uuid = ebooks_groups.ebookuuid
INNER JOIN groups_users ON ebooks_groups.groupuuid = groups_users.groupuuid
INNER JOIN groups ON groups_users.groupuuid = groups.uuid
WHERE useruuid=".$get_useruuid."
ORDER BY groups.name");
1/ However i need to grab another column from the groups table - namely groups.uuid
i tried
SELECT DISTINCT movies.*, groups.* FROM movies, groups
&
SELECT DISTINCT movies.*, groups.name, groups.uuid FROM movies, groups
but it retrieved no records.
2/ Then I had another look at my original code - ... FROM movies ... - how is this even working if i'm not selecting FROM movies, groups tables?
AFAIK, this is pure MySQL. PHP or not doesn't come into play.
First to understand is the implicit join:
Explicit vs implicit SQL joins
That understanding should solve at least half of your problem.
Secondly, I'd never code a SELECT * without a very good reason (and there's few). It makes much more sense to select just the columns you need instead of getting them all and even if you need all that are currently there, if you work on the database model later on, there might be more (or less!!) columns in the database and it'll be much harder to detect that your code needs updating if you don't have them explicitly listed.
For the rest I build my SQL queries slowly step by step. That helps a lot to debugging your queries esp. as you have the actual tables and some sample data ...
[That should solve your other half of the question]
Usually linq is using an left outer join for its queries but on some cases it decides to use inner join instead.
I have a situation where that decision results in wrong results since the second table doesn't always have suitable records and that removes the records from the first table.
I'm using a linqdatasource over a dbml where the relevant tables are identical but one holds historical records removed from the first. both have the same primary key. and I'm using a dataloadoption to load both tables at once with out round trips.
Would you explain why linq decided to use an inner join here?
Thanks
No, unfortunately you are incorrect. The LINQ Join operator always does an inner join. http://www.hookedonlinq.com/JoinOperator.ashx
If you want to do a left outer join, you need to use a combination of select or foreach. See these examples:
http://solidcoding.blogspot.com/2007/12/left-outer-join-in-linq.html
http://social.msdn.microsoft.com/Forums/en-US/linqprojectgeneral/thread/c139313e-d745-4e1d-b3dc-ab355507eb48
or google it, there are a ton of examples out there.
It is better practice not to use the join operator where possible, and rely on traversing the relationships set up in the data context between the entities.
from r in Rabbits
select
{
r.Name
r.Parent.Name
}
This will automatically traverse the parent relationship and decide on the appropriate sql to run.
Using .DefaultIfEmpty() appropriately will mean that any NULL entries are added, hence it is translated into the appropriate outer join. This can be used with the join operator by including an 'into'.
JOIN and LEFT JOIN equivalent in LINQ