Getting count of cases of a variable from one table such that its entries are different in an another column of different table in SQLlite? - sql

So here it is,
I've from customers table:
customersid (unique for each customers)
customers' city
from invoices table:
billing city
customers id
Now i've to find customers id whose billing city is different from city they live (customers_city). My code is this:
Select Customers.customerid, Customers.city, Invoices.Billingcity
From Customers Inner join
Invoices
ON customers.city <> invoices.billingcity
Now the problem is that count of unique customer_id (1,2,3,4) and number of mismatch cases in another column. But what I am getting is something like this:
(read it like this, after billing city, when the 1 (customer_id) repeats it indicates its a new entry).. I don't know how to format this column, sorry
CustomerId | City | BillingCity |
| 1 | São José dos Campos | Stuttgart |
| 1 | São José dos Campos | Oslo |
| 1 | São José dos Campos | Brussels |
(Output limit exceeded, 10 of 23812 total rows shown)

You need to join on the customer id and then compare the cities:
Select c.customerid, c.city, i.Billingcity
From Customers c join
Invoices i
on c.customerid = i.customerid
where c.city <> i.billingcity;

Related

Oracle SQL query partially including the desired results

My requirement is to display country name, total number of invoices and their average amount. Moreover, I need to return only those countries where the average invoice amount is greater than the average invoice amount of all invoices.
Query for Oracle Database
SELECT cntry.NAME,
COUNT(inv.NUMBER),
AVG(inv.TOTAL_PRICE)
FROM COUNTRY cntry JOIN
CITY ct ON ct.COUNTRY_ID = cntry.ID JOIN
CUSTOMER cst ON cst.CITY_ID = ct.ID JOIN
INVOICE inv ON inv.CUSTOMER_ID = cst.ID
GROUP BY cntry.NAME,
inv.NUMBER,
inv.TOTAL_PRICE
HAVING AVG(inv.TOTAL_PRICE) > (SELECT AVG(TOTAL_PRICE)
FROM INVOICE);
Result: Austria 1 9500
Expected: Austria 2 4825
Schema
Country
ID(INT)(PK) | NAME(VARCHAR)
City
ID(INT)(PK) | NAME(VARCHAR) | POSTAL_CODE(VARCHAR) | COUNTRY_ID(INT)(FK)
Customer
ID(INT)(PK) | NAME(VARCHAR) | CITY_ID(INT)(FK) | ADDRS(VARCHAR) | POC(VARCHAR) | EMAIL(VARCHAR) | IS_ACTV(INT)(0/1)
Invoice
ID(INT)(PK) | NUMBER(VARCHAR) | CUSTOMER_ID(INT)(FK) | USER_ACC_ID(INT) | TOTAL_PRICE(INT)
With no sample data, we can't really tell whether this:
Expected: Austria 2 4825
is true or not.
Anyway: would changing the GROUP BY clause to
GROUP BY cntry.NAME
(i.e. removing additional two columns from it) do any good?
`SELECT C.COUNTRY_NAME,COUNT(I.INVOICE_NUMBER),AVG(I.TOTAL_PRICE) AS AVERAGE
FROM COUNTRY AS C JOIN CITY AS CS ON C.ID=CS.COUNTRY_ID
JOIN CUSTOMER AS CUS ON CUS.CITY_ID=CS.ID
JOIN INVOICE AS I ON I.CUSTOMER_ID=CUS.ID
GROUP BY C.COUNTRY_NAME,C.ID
HAVING AVERAGE>(SELECT AVG(TOTAL_PRICE) FROM INVOICE`
would changing the GROUP BY clause to
GROUP BY cntry.NAME , cntry.ID
Fix your group by columns.
Keep only cntry.name.
It will work.
This is a hackerrank question.

Finding duplicate rows and related records

I have a database that was migrated into a new schema. The old database had no referential integrity and so I need to get rid of lots of duplicates.
I have a table of RegisteredVehicles:
id | plate | state
# | 1425 | il
# | 3322 | il
And a table of ParkingRequests:
id | date | registeredVehicleId (FK)
# | 2/2/12 | #
The relatoinship is one to many - one registered vehicle to many requests.
The following query gets me each duplicate record by Plate and State and also outputs each RegisteredVehicle's Id.
select Id, Plate, [State] from RegisteredVehicles where Plate in (
select plate from RegisteredVehicles group by Plate having count(*) > 1
)
Which gives me something like this
Id Plate State
036d59f1-d928-40f2-b373-049122202bff 0000000 IL
615e2fab-8b43-4e42-b6f0-268038bba949 0000000
I am trying to get a count of parking request per each vehicle row returned in the above code block. Something like this
Id | Plate | State | # Requests
1 | 222 | IL | 2
2 | 333 | IL | 4
But am having issues making the query more complex than it already is. This itself took me quite a while to get working.
Please try this query :
SELECT
A.ID,
A.PLATE,
A.STATE AS [STATE],
COUNT(A.ID) AS [NO OF REQUESTS]
FROM REGISTEREDVEHICLES A
LEFT JOIN PARKINGREQUESTS B
ON B.REGISTEREDVEHICLEID = A.ID
WHERE
A.PLATE IN(
SELECT
PLATE
FROM REGISTEREDVEHICLES
GROUP BY PLATE
HAVING COUNT(*) > 1
)
GROUP BY
A.ID,
A.PLATE,
A.STATE

selecting rows the id's of which appear in a column of another table

I can't quite get my head around a SQL query because it is not my forté. I'm trying to select the names of rows in an employees table the id's of which appear in a column salesPersonId of another table, accounts. That is, any employee name which is represented in the accounts table.
ACCOUNT
+----+---------------+
| id | salesPersonID |
+----+---------------+
| 0 | 1020 |
+----+---------------+
| 1 | 1020 |
+----+---------------+
| 2 | 1009 |
+----+---------------+
EMPLOYEE
+------+---------------+
| id | firstName |
+------+---------------+
| 1009 | BILL | <-select his name
+------+---------------+
| 1020 | KATE | <-select her name
+------+---------------+
| 1025 | NEIL | <-not this guy
+------+---------------+
Since Neil hasn't got any presence in account.salesPersonID, I'd like to select the other two besides him. I'm not getting very far with it though, and looking for some input.
SELECT * FROM employee e
LEFT JOIN account a
ON a.salesPersonID = e.id
WHERE (SELECT COUNT(salesPersonID) FROM account) > 0
does not work. I wonder how I could select these employee names that are present in salesPersonID. Thank you.
Try this:
SELECT Distinct e.firstName
FROM employee e
JOIN account a ON a.salesPersonID = e.id
The JOIN will take care of the filtering to make sure that you are only returning the records that exist in both tables.
Distinct will make sure that you are only getting each firstName value one time. You can also accomplish this by Grouping by employee.Id or employee.firstName (grouping by Id is the better strategy if you want to return one row for each unique employee, even if they have the same first name, grouping on firstName or using distinct is for when you just want one of each unique name, even if the name is used by more than one employee)
u can have the query like this....
select e.firstname from employees1 e left join account a on(e.id=a.salespersonid)
where e.id= a.salespersonid
group by e.firstname
result:
firstname
bill
kate

Oracle WITH clause and grouping by results

I have two tables: a product table and a territory table. The product tables holds IDs of products and the territory code denoting which countries they can be sold in:
PRODUCT:
PRODUCT_ID | TERRITORY_CODE
----------------------------
PROD1 | 2
PROD2 | 0
PROD3 | 1
PROD4 | 0
PROD5 | 2
PROD6 | 0
PROD7 | 2
The second table table holds a territory code and the corresponding ISO code of countries it's allowed to be sold in. For example:
TERRITORY:
TERRITORY_CODE | COUNTRY_CODE
---------------------------
0 | US
1 | CA
2 | US
2 | CA
I would like to write a query that counts the number of PRODUCT_IDs using COUNTRY_CODE as a key.
For example, I want to know how many distinct products there are for sale in the US. I don't want to have to know that 0 and 2 are territory codes that contain the US, I just want to look up by COUNTRY_CODE. How can I do this?
In some preliminary research, I've found that a WITH clause may be useful, and came up with the following query:
WITH country AS (
SELECT (DISTINCT COUNTRY_CODE)
FROM TERRITORY
)
SELECT COUNT(DISTINCT PRODUCT_ID)
FROM country c,
PRODUCT p
WHERE p.TERRITORY_CODE=c.TERRITORY_ID;
However, this doesn't produce the expected result. I also can't get it to group by COUNTRY_CODE. What am I doing wrong?
Looks like you need to use GROUP BY. Try something like this:
SELECT T.Country_Code, COUNT(DISTINCT PRODUCT_ID)
FROM Product P
JOIN Territory T ON P.Territory_Code = T.Territory_Code
GROUP BY T.Country_Code
And the SQL Fiddle.
Good luck.

Unexpected query results with multiple joins - mysql

I have a multi-table setup to handle online purchase transactions. The main table I'm getting data from is a purchase activity table. It contains ShipAcctID, which connects it to an addresses table, and AcctID, which connects it to a users table - sort of. The AcctID field is a reference to the user's account ID, which is stored in the users table, but what I need to return is their shipping address, which is connected in the addresses table via the customer_id field.
To try to clear that up, here's what the tables actually look like.
Purchases table
ID | PurchAmt | AcctID | ShipAddrID
================================================
1 | 30.99 | 25 | 420
2 | 45.22 | 31 | 209
Users table
ID | Name
=================================
25 | Anastasia Beaverhausen
31 | Charles Beaverhausen
45 | Bennie Beaverhausen
Addresses table
ID | customer_id | name | address
==========================================================================
300 | 25 | Anastasia Beaverhausen | 123 Park Avenue
209 | 31 | Charles Beaverhausen | 500 5th Avenue
420 | 45 | Bennie Beaverhausen | 500 North Michigan Avenue
What I need to do is return something like this:
PurchaseID | PurchAmt | billname |billAddress |shipName | shipaddress
====================================================================================================================================
1 | 30.99 | Anastasia Beaverhausen |123 Park Avenue |Bennie Beaverhausen |500 North Michigan Avenue
So I need to get the billaddress by joining purchases to addresses via the purchases.AcctID = addresses.customer_id relationship; then get the shipaddress by joining purchases directly to addresses via the purchases.ShipAddrID = addresses.id relationship. It makes sense in my head, anyway. But when I run the query, I get multiple rows per purchase ID, like this:
PurchActvtyID | billName | billAddress1 |shipName | shipAddress1
==================================================================================================================================
1535 | Anastasia Beaverhausen | 123 Park Avenue |Bennie Beaverhausen | 500 North Michigan Avenue
1535 | Bennie Beaverhausen | 500 North Michigan Avenue | Bennie Beaverhausen | 500 North Michigan Avenue
Can anyone explain why this is happening? I'm sure it's probably something to do with which kind of join to use, but I can't seem to get the correct results no matter which kind I try. Here's my query:
SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a2.name AS shipName, a2.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id
LEFT OUTER JOIN jos_customers_addresses a2 ON p.ShipAddrID = a2.id
ORDER BY p.PurchActvtyID ASC
EDITS
results of Stephen's query:
PurchActvtyID | billName | shipName | billAddress | shipAddress
========================================================================================
1535 | Esther Strom | Esther Strom |123 Park Avenue | 500 North Michigan Avenue
1535 | Esther Strom | Esther Strom |500 North Michigan Avenue |500 North Michigan Avenue
The reason for the name being different from what I showed in my example of desired outcome is that your query is pulling the name from the users table, which isn't accurate - the user name isn't necessarily the same as the billing or shipping name asssociated with a given user. This is why I need to pull those values from the addresses table, not the users table.
Although there aren't duplicates as such, you can have multiple addresses for a single customer ID - this is what appears to be happening in the example, as a single purchase (1535) is returning multiple billing addresses (both 123 Park Avenue and 500 North Michigan Avenue).
Normally, a customer could have many billing addresses (over time), although there is normally only one billing address per transaction. I therefore suggest adding a BillAddrID field to arrc_PurchaseActivity (if it doesn't already have one), and changing the linkage to jos_customers_addresses alias a1 to be p.BillAddrID = a2.id.
Alternatively, you may want (or already have) only one billing address per customer, in which case you should add a billing address ID field to your customer table (users, in the question), and then change the query to link from the purchase table to the customer table, and then from the customer's billing address ID to the address table, to return a single billing address for the transaction.
EDIT, following comments:
The following query should resolve the issue of multiple addresses being returned on the billing alias:
SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a2.name AS shipName, a2.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id and a1.billing = 1
LEFT OUTER JOIN jos_customers_addresses a2 ON p.ShipAddrID = a2.id
ORDER BY p.PurchActvtyID ASC
To create the output you want you only need two tables:
Purchases table
Addresses table
However, you need to join to the Addresses table twice:
Once for the Billing Address
Once for the Shipping Address
SELECT
t1.ID as PurchaseID,
t1.PurchAmt as PurchAmt,
t2.name as billname,
t2.address as billaddress,
t3.name as shipname,
t3.address as shipaddress
FROM Purchases t1
INNER JOIN Addresses t2
ON t1.AcctID
= t2.customer_id
INNER JOIN Addresses t3
ON t1.ShipAddrID
= t3.ID
The 1st INNER JOIN links to the billing information
The 2nd INNER JOIN links to the shipping information
I did get an answer to this on experts-exchange. All I needed to do was use a group by clause. So my query now looks like this:
SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a2.name AS shipName, a2.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id
LEFT OUTER JOIN jos_customers_addresses a2 ON p.ShipAddrID = a2.id
GROUP BY p.PurchActvtyID
ORDER BY p.PurchActvtyID ASC
I don't think there's a reason to join the same table twice based on your criteria...
Try:
SELECT p.PurchActvtyID, a1.name AS billName, a1.address1 AS billAddress1, a1.name AS shipName, a1.address1 AS shipAddress1
FROM arrc_PurchaseActivity p
LEFT OUTER JOIN jos_customers_addresses a1 ON p.AcctID = a1.customer_id AND p.ShipAddrID = a1.id
ORDER BY p.PurchActvtyID ASC
Note - I work with SQL Server, I'm assuming syntax will work with MySQL.
Edit:
I suspect it's happening because you are doing two left outer joins to the same table on different criteria.