I am trying to write a view to show name, and wrong_zipcode for the customer that has an incorrect zipcode in the customers table below, assume we have another table call usstates that has the correct zipcodes.
My code looks this way:
create view test as select name, zipcode from Customer c,usstates u where c.zipcode not in (select zipcode from usstates);
Customer table
usstates table
If I understand you question right, you got two tables. One with customer information and one with zip codes and you want to find all rows in the customer table where the zip code entered does not exist in the zip code table?
In that case you could use something like this.
SELECT NAME, ZIPCODE from Customers where not exists (SELECT TOP 1 ZIPCODE from MyZipCodeTable where Customers.ZIPCODE = MyZipCodeTable.ZIPCODE)
What do you think about that? We join the two tables with the zipcode and we eliminate the rows where the state doesn't match.
CREATE VIEW customers_with_wrong_zipcode AS
SELECT customers.customer_id, customers.zipcode AS wrong_zipcode, customers.state
FROM customers
INNER JOIN us_states ON us_states.zipcode = customers.zipcode
WHERE us_states.state <> customers.state;
You can use not exists
Select *
From customers c
Where not exists
(select 1 from usstates where zipcode = c.zipcode);
Related
I have a MySQL database that's basically got this setup:
The customer records have many address records associated to them, and have an internal_id text value.
The orders also have a single ship to address record associated to them.
However, I had a bug, and I'm hoping to solve this issue without code.
I need to match the name, address_one and city against the address record on the customer (they should have only 1 match) and assign the internal_id from that to the address on the orders address record.
I've tried this, but it's not working so far:
UPDATE address AS addr
LEFT JOIN Orders AS O ON addr.id = O.ship_to_id
SET addr.`internal_id` = (
SELECT internal_id (
SELECT *
FROM address
WHERE address.name = addr.name
AND address.`address_line_one` = addr.`address_line_one`
AND address.`city` = addr.`city`
) AS a_int_id)
WHERE O.deleted_at IS NULL;
have you tried creating another table?
for example: customers_address_table
with columns:
cus_add_id pk
customer_id
address_id
then in your orders table:
ship_id pk
cus_add_id
I have table contacts with more than 1,000,000 and other table cities which have about 20,000 records. Need to fetch all cities which have used in contacts table.
Contacts table have following columns
Id, name, phone, email, city, state, country, postal, address, manager_Id
cities table have
Id, city
I used Inner join for this, but its taking a long time to go. Query takes more than 2 minutes to execute.
I used this query
SELECT cities.* FROM cities
INNER JOIN contacts ON contacts.City = cities.city
WHERE contacts.manager_Id= 1
created index on manager_Id as well. But still its very slow.
for better performance you could add index
on table cities column city
on table contacts a composite index on columns (manager_id, city)
Filter contacts first and then join to cities:
SELECT ct.*
FROM cities ct INNER JOIN (
SELECT city FROM contacts
WHERE manager_Id = 1
) cn ON cn.city = ct.city
You need indexes for city in both tables and for manager_id in contacts.
As others have pointed out about having proper index, I am taking it a bit more for clarification. You are specifically looking for contacts where the MANAGER ID = 1. This is not expected to be one person, but could be many people. So having the MANAGER ID in the first position will optimize get me all people for that manager. By having the city as part of the index via (manager_id, city), you are pulling the two data elements you need to optimize as part of the index. This way the engine does not have to go to the raw data pages to get the other part of interest.
Now, From that, you want all the city information (hence the join to city table on that ID).
Since you are only querying the CITIES and not the actual contact people information, you probably want to have DISTINCT City ID. Lets say a manager is responsible for 50 people and most of them live in the same city or neighboring. You may have 5 distinct cities? That too will limit your result set of joining.
Having said that, I would do a follows, and with MySQL, using STRAIGHT_JOIN can help optimize by "do the query as I wrote it, don't think for me".
select STRAIGHT_JOIN
cty.*
from
( select distinct c.City
from Contacts c
where c.Manager_ID = 1 ) PQ
JOIN Cities cty
on PQ.City = Cty.City
The "PQ" is an alias representing my "pre-query" of just DISTINCT cities for a given manager.
Again, have one index on Contacts table on (manager_id, city). On the city table, I would expect and index on (city).
You need two indexes, one on each table.
On the contacts table, first index manager_Id, then City
CREATE INDEX idx_contacts_mgr_city ON contacts(manager_Id, City);
On the cities table, just index `City.
Is the 'City' field from the table 'Contacts' a VARCHAR?
If that's the case, I see multiple things here.
First of all, since you have already have the 'Id' for the corresponding city in your 'cities' tables, I don't see why not to use the same 'Id' from the 'cities' table for the 'Contacts' table.
You can add the 'IdCity' field to the 'Contacts' table so you don't have to modify your existing records.
You'll have to insert the 'IdCity' manually though for each of your records, or you can create a Query using 'cities' table and then compare the 'idCity' but insert the 'city' (city name) in your 'Contacts' table.
Returning to your query:
Then, use an INT JOIN instead of a VARCHAR JOIN. Since you have many records, this can show up an important significance in performance.
It looks like you need to add two indexes, one on cities.city and one on (contacts.manager_Id, contacts.city). That should speed things up significantly.
Here's what i am trying to achieve:
Table one shows where certain products SHOULD be located on a system.
Table two shows where the products ACTUALLY are based on a live environment.
What i would like is to only return rows in Table Two IF they are in the incorrect location based on TABLE ONE.
Below is how the tables would look:
I've tried putting together my own query as below
SELECT product, location
FROM Table 2
WHERE product, location NOT IN
(SELECT product, location
FROM Table 1)
ORDER BY LOCATION
This should work:
select *
from table1
join table2 on table1.product=table2.product
and table1.location <> table2.location
We want to select customers based on following parameters i.e. customer should be in:
specific city i.e. cityId=1,2,3...
specific customerId should be excluded i.e. customerId=33,2323,34534...
specific age i.e. 5 years, 7 years, 72 years...
This inclusion & exclusion list can be any long.
How should we design database for this:
Create separate table 'customerInclusionCities' for these inclusion cities and do like:
select * from customers where cityId in (select cityId from customerInclusionCities)
Some we do for age, create table 'customerEligibleAge' with all entries of eligible age entries:
i.e. select * from customers where age in (select age from customerEligibleAge)
and Create separate table 'customerIdToBeExcluded' for excluding customers:
i.e. select * from customers where customerId not in (select customerId from customerIdToBeExcluded)
OR
Create One table with Category and Ids.
i.e. Category1 for cities, Category2 for CustomerIds to be excluded.
Which approach is better, creating one table for these parameters OR creating separate tables for each list i.e. age, customerId, city?
IN ( SELECT ... ) can be very slow. Do your query as a single SELECT without subqueries. I assume all 3 columns are in the same table? (If not, that adds complexity.) The WHERE clause will probably have 3 IN ( constants ) clauses:
SELECT ...
FROM tbl
WHERE cityId IN (1,2,3...)
AND customerId NOT IN (33,2323,34534...)
AND age IN (5, 7, 72)
Have (at least):
INDEX(cityId),
INDEX(age)
(Negated things are unlikely to be able to use an index.)
The query will use one of the indexes; having both will give the Optimizer a choice of which it thinks is better.
Or...
SELECT c.*
FROM customers AS c
JOIN cityEligible AS b ON b.city = c.city
JOIN customerEligibleAge AS ce ON c.age = ce.age
LEFT JOIN customerIdToBeExcluded AS ex ON c.customerId = ex.customerId
WHERE ex.customerId IS NULL
Suggested indexes (probably as PRIMARY KEY):
customers: (city)
customerEligibleAge: (age)
customerIdToBeExcluded: (customerId)
In order to discuss further, please provide SHOW CREATE TABLE for each table and EXPLAIN SELECT ... for any of the queries actually work.
If you use the database only that operation, I recommend to use the first solution. Also the first solution is very simple to deploy.
The second solution fills up with junk the DB.
I'm having some trouble figuring out a query. I have 2 tables, COMPANY, which contains a company id column, comp_id, and a name column. The second table, SOURCE, has a column for comp_id and a column for parts the company sells, parts.
How can I write a query to find the names of companies that produce all parts? I've figured that this uses not exist statements, but i can't figure out how.
Thanks.
Try this...
SELECT c.name from company join source s on (s.comp_id = c.comp_id) where parts = [:part_id];
Select name
from company, source
where company.comp_id=source.comp_id;
SELECT name, count(*) AS parts_count
FROM company, source
WHERE company.comp_id = source.comp_id
GROUP BY name
HAVING parts_count = (select count(*) from source)
Is very simple and command, suppose a part is "875"
SELECT name FROM company WHERE comp_id IN(SELECT comp_id FROM parts
WHERE parts = 875)
this allow you have the same part in distinct companies
Select name from companies,source where companies.comp_id=source.comp_id;