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

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

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.

Select entire row on group by aggregation

I'm having some struggle with something that should be a simple SQL query.
This is my initial database schema:
Also prepared the example in SQLFiddle
The query I've ended up with is:
select
b.ad_id,
b.auction_id,
max(b.amount) as max,
max(b.created_at) created_at
from bid b
where b.user_id = '601'
group by b.ad_id, b.auction_id
But in the result, I need the whole row from the bid table:
select
b.id,
b.ad_id,
b.auction_id,
max(b.amount) as max,
max(b.created_at) created_at
from bid b
where b.user_id = '601'
group by b.ad_id, b.auction_id
Which fails with: [42803] ERROR: column "b.id" must appear in the GROUP BY clause or be used in an aggregate function Position: 16. Cannot add the id field in the GROUP BY clause, because it will add some extra rows I don't need.
What I need is to select from the bid table the highest record (amount field) grouped by auction_id and ad_id.
I think I need to make some self inner join or subselect but right now I'm not able to write the SQL.
What I need is to select from the bid table the highest record (amount field) grouped by auction_id and ad_id
Take a look at DISTINCT ON in the docs. Your desired result would be obtained by the following query.
select DISTINCT ON (b.ad_id, b.auction_id)
b.id,
b.ad_id,
b.auction_id,
b.amount
b.created_at
from bid b
where b.user_id = '601'
ORDER BY b.ad_id, b.auction_id, b.amount DESC
If you want the most recent row for each auction for the given user, then you can use a correlated subquery to filter:
select b.*
from bid b
where b.user_id = '601' and
b.created_at = (select max(b2.created_at)
from bid b2
where b2.auction_id = b.auction_id and
b2.user_id = b.user_id
);
This seems like a sensible interpretation of what you want. I don't know if ad_id is needed.

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.

SQL SELECT and SUM from three

I have been cracking my head for hours on what I thought to be simple SQL SELECT command. I searched every where and read all questions related to mine. I tried an SQL Command Builder, and even read and applied complete series of SQL tutorials and manuals to try to build it from scratch understanding it (which is very important for me, regarding next commands I'll eventually have to build...).
But now I'm just stuck with the results I want, but on separates SELECT commands which I seem to be unable to get together !
Here is my case : 3 tables, first linked to the second with a common id, second linked to the third with another common id, but no common id from the first to the third. Let's say :
Table A : id, name
Table B : id, idA, amount
Table C : id, idB, amount
Several names in Table A. Several amounts in Table B. Several amounts in Table C. Result wanted : each A.id and A.name, with the corresponding SUM of B.amount, and with the corresponding SUM of C.amount. Let's say :
A.id
A.name
SUM(B.amount) WHERE B.idA = A.id
SUM(C.amount) WHERE C.idB = B.id for each B which B.idA = A.id
It's okay for "the first three columns", and "the first two columns and the fourth", both with a WHERE clause and/or a LEFT JOIN. But I can't achieve cumulating all fourth columns together without messing everything !
One could say "it's easy, just put an idA column in Table C" ! Should be easier, sure. But is it really necessary ? I don't think so, but I could be wrong ! So, I just please anyone (who I will give an eternal "SQL God" decoration) with SQL skills to answer laughing "That's so simple ! Just do that and you are gone ! Stupid little newbies..." ;)
Running VB 2010 and MS SQL Server
Thanks for reading !
Try this:
SELECT A.Id, A.Name, ISNULL(SUM(B.amount), 0) as bSum, ISNULL(SUM(C2.Amount), 0) as cSum
FROM A
LEFT OUTER JOIN B ON A.Id = B.idA
LEFT OUTER JOIN (SELECT C.idB, SUM(C.AMOUNT) AS Amount FROM C GROUP BY C.idB) AS C2 ON C2.idB = B.Id
GROUP BY A.Id, A.Name
Try this:
SELECT
a.id,
a.name,
sum(x.amount) as amountb,
sum(x.amountc) as amountc
from a
left join (
select
b.id,
b.ida,
b.amount,
SUM(c.amount) as amountc
from b
left join c
on b.id = c.idb
group by
b.id,
b.amount,
b.ida
) x
on a.id = x.ida
group by
a.id,
a.name
This should give you the result set you're looking for. It sums all C.Amount's for each B.id, then adds it all together into a single result set. I tested it with a bit of sample data in MSSQL, and it works as expected.
Select a.id, a.name, sum(b.amount), sum(c.amount)
from a inner join b on a.id = b.idA
inner join c on b.id = c.idB
group by a.id, a.name
You need to add them separately:
select a.id, a.name, (coalesce(b.amount, 0.0) + coalesce(c.amount, 0.0))
from a left outer join
(select b.ida, sum(amount) as amount
from b
group by b.ida
) b
on a.id = b.ida left outer join
(select b.ida, sum(amount) as amount
from c join
b
on c.idb = b.id
group by b.ida
) c
on a.id = c.ida
The outer joins are to take into account when b and c records don't both exist for a given id.

Sql Query with unique column value

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.