Sql Query with unique column value - sql

My goal is to get a query written. I have three tables, A, B and C. The tables are written such that A.bID = B.bID, and B.cID = C.cID. This basically allows me to write a query where I link a record from a to b, and link the b record to a record from c. So far so good, simple query.
What my problem is... one of the columns included in the query (let's call it C.col3) has to have unique values; the values in this column can only show up once in the query result, but other columns from the other tables do not have this requirement.
Can anybody help me write this query?
Thanks...
Update 1:
Here is the table layout (sorry, I have to use generic names)
Table A
aID, bID, aCol1, aCol2, aCol3 ... aCol10
Table B
bID, cID, bCol1, bCol2, bCol3 ... bCol10
Table C
cID, cCol1, cCol2, col3, cCol4 ... cCol10
Without the unique value constraint in col3, I would write the query like this:
SELECT
A.aID, A.bID, A.aCol1 ... A.aCol10,
B.bID, B.cID, B.bCol1 ... B.bCol10,
C.cID, C.cCol1, C.cCol2, C.col3 ... C.cCol10
FROM
A, B, C
WHERE
A.bID = B.bID AND B.cID = C.cID
... but of course that doesn't make sure the that values in C.col3 are unique.
Update 2:
More info...
Table A and Table B have a one to many relationship; A is the "header", B is the "item".
Table B and Table C have a one to one relationship.
These tables are part of a caching mechanism, so lots of data that looks similar, but is still different in some cols.
Since A is the header, most of the duplicate values will be found in A.
I first need to order the rows by A.aID, but then after that I only need the first rows returned, where the value for C.col3 does not appear in a previous row for that col.
Does that make things a little clearer, or am I still not making any sense? :)
Final Update:
I chose Bartosz Klimek's answer as it was the closest to what I needed; I just had to modify the nested join clause in the middle.
Thank you all for your help!

I'm going to quickly make a little example of what you're trying to do and hopefully this will help clarify why what you are asking (currently) is impossible.
If you had a Customer Table [CustomerID, CustomerName] and an Orders Table [OrderID, CustomerID, DollarAmount]
If you wanted all orders for customers:
SELECT CustomerName, OrderID, DollarAmount
FROM Customer, Orders
WHERE Customer.CustomerID = Orders.CustomerID
it would return
"Acme Corp.", 1, $2300
"Acme Corp.", 2, $3022
"A company", 3, $1234
Everything is good.
But the equivalent of your question is asking for this query, but with unique CustomerNames. What would you display for OrderID and DollarAmount beside "Acme Corp"?
You could use aggregates to display something,
SELECT CustomerName, MAX(OrderID), SUM(DollarAmount)
FROM Customer, Orders
WHERE Customer.CustomerID = Orders.CustomerID
GROUP BY Orders.CustomerID
But I believe that you mentioned that you do not want to use aggregates.
Does this explain the issue clearly?

I started to post another answer, but after rethinking it I deleted it. If I am reading the question correctly, I think this is an impossible/illogical question. Let me explain with an example. if I read this wrong, please clarify the question with an exampe of what you are looking for.
Table A
BID COL1
1 Value1
2 Value1
3 Value2
Table B
BID CID COL 2
1 4 ValueX
2 5 ValueY
3 6 ValueZ
Table C
CID COL3
4 Value#
5 Value#
6 Value~
Expected Result
A.Col1 A.BID B.BID B.CID B.COL2 C.CID C.COL3
Value1?? 1 1 4 ValueX 4 Value#
Value1?? 2 1 5 ValueY 5 Value#
Value2 3 3 6 ValyeZ 6 Value~
Per the question you don't want value1 repeated in the first column, but what do you propose goes into the second row where it would normally be repeated if you didn't have the unique constraint?

SELECT A.*, B.*, C.*
FROM C
JOIN B ON B.cID = C.cID
JOIN A ON A.bID = B.bID
JOIN
(
SELECT id = min(aID)
FROM C
JOIN B ON B.cID = C.cID
JOIN A ON A.bID = B.bID
GROUP BY col3
) D ON D.id = A.aID
Note that the subquery at the end assures that for each col3 value you will have at most one record in the final resultset. The record selected is the one with the minimal aID. Obviously I assume that aID, bID and cID are primary keys of A, B and C, respectively.

select distinct c.col3 from c inner join b on c.cID = b.cID inner join a on b.bID = a.bID

If you need other values from the tables as well, use:
select max(a.col1), sum(b.col2), col3 from a, b, c
where A.bID = B.bID, and B.cID = C.cID
group by C.col3
On all columns not grouped by you need to use aggregate functions such as
AVG: Average of the column.
COUNT: Number of records.
MAX: Maximum of the column.
MIN: Minimum of the column.
SUM: Sum of the column.

Related

SQL 3 tables (long time ago)

I haven't done a SQL statement in about 10 years. A little help?
Table A:
ID, Title
1,"hello"
2,"world"
Table B:
ID, OBJ_ID
1,23
2,24
Table C:
ID, Name
23,"foo"
23,"bar"
24,"hi"
24,"pangea"
A.ID = B.ID
B.OBJ_ID = C.ID
One (A) to One (B) to Many (C)
Result needed:
A.Title, C.Name(s)
hello,foo,bar
world,hi,pangea
Thanks.
I know I'm flat out asking for answer, but which JOIN would I use? Thanks.
MariaDB, I'm trying to extract some data from someone's WP site. Why table B is there, is beyond me.
Thanks #jarlh
select a.title, c.name
from c
join b on b.obj_id = c.id
join a on a.id = b.obj_id
SELECT A.Title, C.Name
FROM A join B on A.ID=B.ID JOIN C ON B.ID=C.ID
ORDER BY A.Title, C.Name
If you want to have one row per title with all values from table C, consider using pivot.

How to ignore lines in sql query which specific id php

I have a simply shop with php and I need to ignore some products in shop on manage page. How to possible to make ignore in SQL query?
Here is my query:
$query = "SELECT a.*,
a.user as puser,
a.id as pid,
b.date as date,
b.price as price,
b.job_id as job_id,
b.masterkey as masterkey
FROM table_shop a
INNER JOIN table_shop_s b ON a.id = b.buyid
WHERE b.payok = 1
ORDER BY buyid";
I need to ignore list with product_id = "3","4" from table table_shop_s in this query
WHERE b.payok = 1 AND tablename.product_id != 3 AND tablename.product_id != 4
Simply use NOT IN (to ignore specific pids), with AND logical condition. Use the following:
$query = "SELECT a.*,
a.user as puser,
a.id as pid,
b.date as date,
b.price as price,
b.job_id as job_id,
b.masterkey as masterkey
FROM table_shop a
INNER JOIN table_shop_s b ON a.id = b.buyid
WHERE b.payok = 1
AND a.id NOT IN (3,4)
ORDER BY buyid";
Other answer has noted you would probably use a "productid NOT IN (3,4)" which would work, but that would be a short-term fix. Extend the thinking a bit. 2 products now, but in the future you have more you want to hide / prevent? What then, change all your queries and miss something?
My suggestion would be to update your product table. Add a column such as ExcludeFlag and have it set to 1 or 0... 1 = Yes, Exclude, 0 = ok, leave it alone. Then join your shop detail table to products and exclude when this flag is set... Also, you only need to "As" columns when you are changing their result column name, Additionally, by doing A.*, you are already getting ALL columns from alias "a" table, do you really need to add the extra instances of "a.user as puser, a.id as pid" ?
something like
SELECT
a.*,
b.date,
b.price,
b.job_id,
b.masterkey
FROM
table_shop a
INNER JOIN table_shop_s b
ON a.id = b.buyid
AND b.payok = 1
INNER JOIN YourProductTable ypt
on b.ProductID = ypt.ProductID
AND ypt.ExcludeFlag = 0
ORDER BY
a.id
Notice the extra join and specifically including all those where the flag is NOT set.
Also, good practice to alias table names closer to context of purpose vs just "a" and "b" much like my example of long table YourProductTable aliased as ypt.
I also changed the order by to "a.id" since that is the primary table in your query and also, since a.id = b.buyid, it is the same key order anyhow and probably is indexed on your "a" table too. the table_shop_s table I would assume already has an index on (buyid), but might improve when you get a lot of records to be indexed on (buyid, payok) to better match your JOINING criteria on both parts.

Generate all combinations that do not already exist between two tables and union them with the ones that already exist SQL

I have 3 tables:
A
B
C
C is an association class between A and B. Meaning that there is a many to many relationship between A and B. C also has fields of its own that are not the primary keys of A/B.
I want to return all the fields in C for a given A.ID (PK). Now this part might return 0 to * results. But I always want to return the same number of results as there are records in B. That is I want to fill in the missing combinations between A.ID and B (that do not exist in C) with Null Values.
SAMPLE:
I am trying to do this within Access.
In case it helps, here is an image with the specific tables and their fields that I am trying to do this with.
Where A is ASCs, B is Flights, and C is FlightHistory.
You will need 2 queries, one that selects all IDs of B together with the desired AID, and one query that selects all these combinations, outer-joined to the existing combinations in C. This can be written in a single query (with a subquery) like this:
SELECT AB.AID, AB.BID, C.Desc
FROM (SELECT A.AID, B.BID FROM A, B WHERE (((A.AID)=1))) AB
LEFT JOIN C ON (AB.BID = C.BID) AND (AB.AID = C.AID);
You could union two result sets together, one which gets the primary records from C with another that gets the missing entries from B...
SELECT * FROM C WHERE C.AID = 1
UNION
SELECT 1 as AID, ID as BID, '' as Desc FROM B WHERE ID NOT IN (SELECT BID FROM C WHERE C.AID = 1)
ORDER BY BID;
http://sqlfiddle.com/#!9/02d110/11/0

Use Join to get record info without returning the row in the query

I have two tables (Apple and Bid). I want to return all rows from A based on a given condition, and I want to get a single value from table B. It will help if I show what I'm trying to do:
Apple
ID
Name
Type
Bid
bid_id
Type
I want to return all records from A where the ID matches a given ID AND I want to get the bid_id associated with each record pulled from table A.
So, my query looks something like this:
"Select A.ID, A.Name, A.Type, B.bid_id
FROM Apple A
LEFT JOIN Bid B on B.Type = A.Type
Where A.ID = 35";
There is only one record in the Apple table with an id of 35. However, since there are three tables in the Bid table whose type matches that of Apple # 35's type, three records are being returned.
To clarify, only one record should be being returned.
Any ideas?
For MySQL:
Select A.ID, A.Name, A.Type, B.bid_id
FROM Apple A
LEFT JOIN Bid B
ON B.Type = A.Type
WHERE A.ID = 35
GROUP BY A.ID
That will return one of the bid_id's. If you have some rule as to which bid_id to choose, you can implement it using aggregation functions - e.g., MIN, MAX, and more complex rules can be implemented as well.
Arbitrarily choosing to return the MIN value:
Select A.ID, A.Name, A.Type, MIN(B.bid_id)
FROM Apple A
LEFT JOIN Bid B
ON B.Type = A.Type
WHERE A.ID = 35
GROUP BY A.ID, A.Name, A.Type;
Given that you're looking for up to one random bid, the fastest option would be limit 1:
select A.ID
, A.Name
, A.Type
, B.bid_id
from Apple A
left join
Bid B
on B.Type = A.Type
where A.ID = 35
limit 1

Joining One table to many using Joins

In this question it's finally clicked how to write joins between multiple tables, where they link in a line e.g.
Table A - Table B - Table C
Where Table A references Table B, and Table B references Table C and so on.
What I still don't understand is how to reference the situation where Table A references Table B as above and also reference Table D.
In implicit Joins I can get the following to work, but want to move it to explicits...
SELECT a.name, b.office, c.firm, d.status
FROM job a, depts b, firms c, statuses d
WHERE a.office = b.ref
AND b.firm = c.ref
AND a.status = d.ref
Any tips?
SELECT
a.name,
b.office,
c.firm,
d.status
FROM
job a
JOIN depts b ON a.office = b.ref
JOIN firms c ON b.firm = c.ref
JOIN statuses d ON a.status = d.ref
That's as detailed as I could get on such an obscure question. You didn't describe what exactly does "link" mean in your case. So I don't know, maybe you need left join.