mysql inner join not working as expected - mysql

Sorry about this. There are a million posts about this. Somehow, I am still missing something. Simple inner join exactly as this:
http://www.w3resource.com/mysql/advance-query-in-mysql/inner-join-with-multiple-tables.php
Clueless what the problem is. Just trying to add the org to the machine record.
I expect that if there is no match on user_name, the machine record will be dropped, or not, but either way, <= number of records in machines. Getting multiples. Machines.machine_name and user_name are not unique in machines as each machine has multiple software packages tracked.
select users2.org, machines.User_name, machines.Machine_name, machines.model, machines.program, machines.version
from machines inner join users2 on users2.user_name = machines.User_name

You probably want to aggregate here because you will get a cartesian product for all of the machines that share a user_name:
select users2.org,
machines.User_name,
machines.Machine_name,
machines.model
from machines
inner join users2 on users2.user_name = machines.User_name
GROUP BY users2.org, machines.User_name, machines.Machine_name, machines.model

Thank you for your input. The issue was that somehow when the data was massaged (user_name was originally email in 1 case and windows network id in the other), the missing user_names in both tables got changed to ' '. This caused join matches all over the place that I was not expecting. The missing user_name fields were supposed to have different default values. I fixed the default values in the machines table and excluded them with "where machines.User_name <> 'Unknown';" Now I am getting the results I expected. Probably nothing to learn here except understand your data better.

Related

SQL Return All Rows Where 2 Values Are Repeated

I am sure this question has already been answered, but I can't find it or the answer was too complicated. I am new to SQL and am not sure how to word this generically.
I have a mySQL database of software installed on devices. My query to pull all the data has more fields and more joins, but for brevity I just included a few. I need to add another dimension to create a report that lists every case where a device has more than one installation of software from the same product family.
sample
Right now I have code kind of like this and it is not doing what I need. I have seen some info on exists but the examples didn't account for multiple joins so the syntax escapes me. Help?
select
devices.name,
sw_inventory.product,
products.family_name,
sw_inventory.ignore_usage,
from sw_inventory
inner join products
on sw_inventory.product=products.product_name
inner join devices
on sw_inventory.device_name=devices.name
where sw_inventory.ignore=0
group by devices.name, products.family_name
There are plenty of answers out there on this topic but I definitely understand not always knowing terminology. you are looking for how to find duplicates values.
Basically this is a two step process. 1 find the duplicates 2 relate that back to the original records if you want those. Note the second part is optional.
So to literally find all of the duplicates of the query you provided
ADD HAVING COUNT(*) > 1 after group by statements. If you want to know how many duplicates add a calculated column to count them.
select
devices.name,
sw_inventory.product,
products.family_name,
sw_inventory.ignore_usage,
NumberOfDuplicates = COUNT(*)
from sw_inventory
inner join products
on sw_inventory.product=products.product_name
inner join devices
on sw_inventory.device_name=devices.name
where sw_inventory.ignore=0
group by devices.name, products.family_name
HAVING COUNT(*) > 1

Not sure where I went wrong on a sql join

The most programming I do is shell scripts or some python or perl, so I have a basic understanding after Googling for a bit. A little background on what i’m doing. We have two inventory systems: Our’s and Their’s. I need to pull information from Their’s to compare with Our’s.
The problem: We need UPC’s to do inventory while They provide SKU’s in their monthly inventory report.
The solution: Join 3 tables. I’m using phpmyadmin to manage a mysql backend on a recent install of Debain Wheezy.
The first query takes every SKU They have in Their inventory, compares it with the UPC in Their listings and, since not every ‘UPC’ is actually a UPC, compares it to the UPC in Our listings. It looks like this:
SELECT TheirListings.upc, SUM(TheirInventory.quantity)
FROM TheirInventory
JOIN TheirListings
ON TheirListings.sku = TheirInventory.sku
JOIN OurListings
ON TheirListings.upc = OurListings.Upc
GROUP BY TheirListings.upc
ORDER BY TheirListings.upc
And it seems to work well. Our system is happy with it and it makes me happy because this reduces manual entry by 96%. Now I need to get everything this didn’t catch: the 4% that does need manual entry. Our tables shortened for brevity like this:
TheirListings TheirInventory OurListings
upc sku upc
sku quantity
I need to select all the SKU’s and associated quantities:
SELECT TheirInventory.sku, SUM(TheirInventory.quantity)
FROM TheirInventory
LEFT OUTER JOIN TheirListings
ON TheirListings.sku = TheirInventory.sku
LEFT OUTER JOIN OurListings
ON TheirListings.upc = OurListings.upc
WHERE OurListings.upc IS NULL
OR TheirListings.upc IS NULL
GROUP BY TheirInventory.sku
ORDER BY TheirInventory.sku
To double check it’s catching the remainder, I did SELECT COUNT(TheirInventory.sku) for both of those queries and another to return the total of sku’s. Adding my two queries gives me exactly 1 more than expected. I’m not sure where I went wrong.
The first thing I would guess is that they're not working on the same datasets. If you ran the first one a few days ago, perhaps some data has changed causing it to show up in the second query?
If not, what I would do is
SELECT SKU
FROM TheirInventory
WHERE SKU IN (<1st query>)
AND SKU IN (<2nd query>)
This will tell you what is showing up in both, and you can diagnose from there.

MySQL query to join 3 tables while finding non-matches

(I could not come up with an concise title)
Hello All
I have been a long time viewer of the site, but after running into an issue I cannot resolve I thought I would sign up to ask a question. I am not sure how to phrase this issue which made searching for help on it difficult and it could very well be that this has been answered and I simply do not know the right search criteria to find the answer. It may also be that there is not an answer for what I am trying to do. Apologies if I have not used the correct procedure to ask.
What I am trying to achieve I can easily do via scripting, and it may be that's really the only appropriate way to do this. My circumstance puts me in a situation where I am being asked if I can do this via MySQL query only.
ISSUE:
Here is the nature of the situation (for which I don't know how to easily summarize into a topic). I have 3 tables in a mySQL database:
Table: account
column: number (unique id)
Table: user
column: number (unique id)
column: account (links the user to an account)
Table: service
column: number (unique id)
column: user (links the service to a user)
column: servdef (the type of service)
Basically an account holds multiple users and each user can hold multiple services.
I have been asked to write a query which will show all accounts (account.number) which do not contain services (service.number) of a particular type (service.servdef). I have seen posts on this site about using NOT EXISTS, but I have not been able to get it to work correctly for my situation. Is this even possible with a single SQL query? Thanks for any help!
Use LEFT JOIN for that since some users have no records on table service. Try,
SELECT a.*
FROM account a
LEFT JOIN `user` b
on a.number = b.account
LEFT JOIN service c
ON b.number = c.`user`
WHERE c.`user` IS NULL OR
c.servdef <> 'particularService'
SQLFiddle Demo
Using NOT EXISTS:
SELECT a.number
FROM account a
WHERE NOT EXISTS (
SELECT u.account
FROM user u INNER JOIN service s ON (u.number = s.user)
WHERE u.account = a.number
AND s.servdef = 'your_particular_type'
)
DEMO (sqlfiddle).
Here is an adaptation of an accepted answer given in another post I saw yesterday.
#servdef is the service type not existing for the accounts you want to find.
select a.number
from account a
inner join user u on a.number = u.account
inner join service s on u.number = s.user
group by a.number
having max(case when s.servdef = #servdef then 1 else 0 end) = 0
(Gordon if you read this, feel free to laugh)
NOT IN is generally the slowest form, but NOT EXISTS may be faster than LEFT JOIN depending on your engine and indexes. Try each one and see.
SELECT a.number
FROM account a
WHERE a.number NOT IN (
SELECT u.account
FROM user u
INNER JOIN service s ON u.number = s.user
WHERE s.servdef = 'your_particular_type'
)
Edit: Wrong reasoning for NOT IN, sorry. Although I find it slightly easier to read than NOT EXISTS it doesn't work well with nullable columns, although I don't think that applies here.
The problem turned out to be that the version of MySQL was too old to support sub queries. One the server was upgraded to new hardware and a modern operating system, the issue was resolved. The other answers are technically correct, but only work in modern versions of MySQL. It was unbeknownst to me at the time of the question that the version of MySQL was a factor. I was not something I even thought to check.

MySQL Update, Set with Where not working?

I have read other posts and I really don't understand what I am doing wrong here because it is such a simple statement.
anything in '()' are comments
Query:
[UPDATE users, sites
SET users.idSiteRegUsers='1'
WHERE sites.SiteActivateSites='DEL' ]
(TBL's to select to update within the whole query)
(Setting the users tbl idSiteRegUsers to 1)
(Where only the sites in tbl sites = DEL)
I've also read http://bugs.mysql.com/bug.php?id=52651 and tried changing the INT to VARCHAR and UPDATING 0 to DEL due to the bug but still same result.
Issue:
I have 2129 records that need updating as found using a simple select statement to understand the number of results.
([SELECT
sites.SiteActivateSites,
sites.id_Sites,
users.idSiteRegUsers,
users.CompanyNameUsers,
sites.LinkNameSites
FROM
users
INNER JOIN sites ON users.idSiteRegUsers = sites.id_Sites
WHERE
sites.SiteActivateSites != '1']) 'simple'
But the UPDATE query updates all 4000+ records, not just the records that = DEL but the ones that are reference to another value e.g. = 1.
Have I missed something?
Cheers,
Joe
Just as with your SELECT command, you need to tell MySQL how the tables are joined: your UPDATE is currently doing a full cartesian product of both tables (with every row in users joined with every row in sites - therefore the WHERE condition filtering on sites is still resulting in a match on every record from users).
Try instead:
UPDATE users JOIN sites ON users.idSiteRegUsers = sites.id_Sites
SET users.idSiteRegUsers='1'
WHERE sites.SiteActivateSites='DEL'

phpmyadmin not returning any records

I have a strange issue when I input this query in phpmyadming:
SELECT DISTINCT E.* FROM Events E, TICKET T WHERE ((E.idEvent=T.IDEvent AND T.Email='david#fakesite.com')OR (E.email = 'david#fakesite.com')) AND E.dateEvent >= '2012-01-27 20:04:28' ORDER BY E.dateEvent ASC
I get not records, no errors found or anything, as if I've never made the query. I strongly beleive the query worked on phpmyadmin before, but now I can't seem to get it working locally or in the server. Two different machines, locally I have MAMP and in the server linux.
Strangest thing is that if the query is done by php, to the very same DB it returns the correct values.
Any idea what is going on?
Thanks.
For starters, your current query risks returning a Cartesian product if T.email is not equal to 'david#air-ticket.com.es'. That's the only part of the WHERE that contains your JOIN condition.
You should consider explicitly stating your JOIN and ON keywords like this (and then your WHERE clause becomes easier to understand):
SELECT DISTINCT E.*
FROM Events E
INNER JOIN TICKET T ON E.idEvent=T.IDEvent
WHERE (T.Email='david#air-ticket.com.es' OR E.email = 'david#myweb.com')
AND E.dateEvent >= '2012-01-27 20:04:28'
ORDER BY E.dateEvent ASC
And do both the Ticket and Events tables contain an email field? Or is one of them a type-o?
For starters, give the above query a try.