emphasized textI have 2 tables. First table have 3 columns namely SupplierId ,SupplierDetailID and entityid and second table has 2 column namely SupplierId and SupplierDetailID. In first table there are more than one combination of SUPPLIERID and Supplierdetailid due more than one entity id..I want to form left join on supplier Id field in such a way that only when suppliersDetailID is blank in first table it should take max value of SupplierDetailID from second tables for that particular SupplierId.
Formed query will give first_table.supplierID,if first_table SupplierDetailID is blank then max of second table SupplierDetailID for particular supplierId,first_table entityid.
enter image description here
This SQL Query will work for you.
SELECT s1.SupplierID,
ISNULL(s1.SupplierDetailID, MAX(s2.SupplierDetailID)) AS SupplierDetailID
FROM s1
LEFT JOIN s2
ON s1.SupplierID = s2.SupplierID
GROUP BY
s1.SupplierID,s1.SupplierDetailID;
s1 is first supplier table.
s2 is second supplier table.
Related
I have a couple of tables.
Table 1 (player_main)
This table has a "id" column which is a UUID type and is the primary key.
Table 2 (game_main)
This table also has an "id" column of the UUID type and is a primary key.
Table 3 (game_members)
This table has a column "member_id" of UUID type which is a primary key and a foreign reference to player_main(id).
There is also an "game_id" column of UUID type which references game_main(id).
My problem is, if a player connects to the server, I want to be able to load up their "game data" by querying the database and receiving all the data to construct their data object. I am given the UUID of the player which is stored in player_main(id). I need to obtain the game_main(id) and a list of all the game member ids that correspond to that game_main(id).
How would I do this? I've attempted to do different types of joins with a where clause to identify the game_members(member_id) but that only returns the row that is correspondent to the member that has just joined, not a column containing all of the members for that game.
Any help is appreciated, thank you.
Edit
I have tried the following query:
SELECT t1.member_id, t2.*
FROM game_members t1
INNER JOIN game_main t2
ON t1.game_id = t2.id
WHERE t1.member_id = <some UID>
which resulted in 1 row and 2 columns. The columns being "game_members.member_id" and "game_main.id". The value for the first column is the UUID that I specified in the where clause and the value for the second column is the UUID of the game. I was expecting to see 2 rows of data with the same "game_main.id" but with different "game_member.member_id"'s, as I have 2 entries in the same game currently.
Edit 2
As requested, I will provide sample data for my tables as well as the output that I wish to see.
Sample Data:
[player_main]
id
------------------------------------|
863fdf91-86fb-49a7-9232-bcb596e3a86f|
7af64cd7-72a2-410f-9b5c-620127fca0ac|
c7b1952a-b263-470f-9cae-9d5e6d7a8186|
[game_main]
id
------------------------------------|
dd76c680-5853-40a6-b757-0457d1a7e95f|
ca4f5b1f-0f8c-4f10-969c-464ccf207d9c|
[game_members]
member_id | game_id
------------------------------------|------------------------------------
863fdf91-86fb-49a7-9232-bcb596e3a86f|dd76c680-5853-40a6-b757-0457d1a7e95f
7af64cd7-72a2-410f-9b5c-620127fca0ac|dd76c680-5853-40a6-b757-0457d1a7e95f
c7b1952a-b263-470f-9cae-9d5e6d7a8186|ca4f5b1f-0f8c-4f10-969c-464ccf207d9c
[desired output]
This is what the game info of the player's current game should look like. The query should take only the player's UUID and return the following if I the UUID was equal to 863fdf91-86fb-49a7-9232-bcb596e3a86f
member_id | game_id
------------------------------------|------------------------------------
863fdf91-86fb-49a7-9232-bcb596e3a86f|dd76c680-5853-40a6-b757-0457d1a7e95f
7af64cd7-72a2-410f-9b5c-620127fca0ac|dd76c680-5853-40a6-b757-0457d1a7e95f
Try doing a self-join of the game_members table. The following query will generate all unique members who have any game in common with games used by a certain player.
SELECT DISTINCT t2.member_id, t1.game_id
FROM game_members t1
INNER JOIN game_members t2
ON t1.game_id = t2.game_id
WHERE t1.member_id = <some UID>
You could break down your problem into:
looking up the player's current game in game_members and then,
looking up the game's current players from the same game_members table
This approach translates to the following query involving a self-join:
select
gm2.member_id,
gm1.game_id
from
game_members gm1
inner join game_members gm2 on
gm1.game_id = gm2.game_id -- lookup the game's current players
where
gm1.member_id = '863fdf91-86fb-49a7-9232-bcb596e3a86f' -- lookup the player's current game
In the database on which I am attempting to create a FullText Search I need to construct a table with its column names coming from one column in a previous table. In my current implementation attempt the FullText indexing is completed on the first table Data and the search for the phrase is done there, then the second table with the search results is made.
The schema for the database is
**Players**
Id
PlayerName
Blacklisted
...
**Details**
Id
Name -> FirstName, LastName, Team, Substitute, ...
...
**Data**
Id
DetailId
PlayerId
Content
DetailId in the table Data relates to Id in Details, and PlayerId relates to Id in Players. If there are 1k rows in Players and 20 rows in Details, then there are 20k rows in Data.
WITH RankedPlayers AS
(
SELECT PlayerID, SUM(KT.[RANK]) AS Rnk
FROM Data c
INNER JOIN FREETEXTTABLE(dbo.Data, Content, '"Some phrase like team name and player name"')
AS KT ON c. DataID = KT.[KEY]
GROUP BY c.PlayerID
)
…
Then a table is made by selecting the rows in one column. Similar to a pivot.
…
SELECT rc.Rnk,
c.PlayerID,
PlayerName,
TeamID,
…
(SELECT Content FROM dbo.Data data WHERE DetailID = 1 AND data.PlayerID = c.PlayerID) AS [TeamName],
…
FROM dbo.Players c
JOIN RankedPlayers rc ON c. PlayerID = rc. PlayerID
ORDER BY rc.Rnk DESC
I can return a ranked table with this implementation, the aim however is to be able to produce results from weighted columns, so say the column Playername contributes to the rank more than say TeamName.
I have tried making a schema bound view with a pivot, but then I cannot index it because of the pivot. I have tried making a view of that view, but it seems the metadata is inherited, plus that feels like a clunky method.
I then tried to do it as a straight query using sub queries in the select statement, but cannot due to indexing not liking sub queries.
I then tried to join multiple times, again the index on the view doesn't like self-referencing joins.
How to do this?
I have come across this article http://developmentnow.com/2006/08/07/weighted-columns-in-sql-server-2005-full-text-search/ , and other articles here on weighted columns, however nothing as far as I can find addresses weighting columns when the columns were initially row data.
A simple solution that works really well. Put weight on the rows containing the required IDs in another table, left join that table to the table to which the full text search had been applied, and multiply the rank by the weight. Continue as previously implemented.
In code that comes out as
DECLARE #Weight TABLE
(
DetailID INT,
[Weight] FLOAT
);
INSERT INTO #Weight VALUES
(1, 0.80),
(2, 0.80),
(3, 0.50);
WITH RankedPlayers AS
(
SELECT PlayerID, SUM(KT.[RANK] * ISNULL(cw.[Weight], 0.10)) AS Rnk
FROM Data c
INNER JOIN FREETEXTTABLE(dbo.Data, Content, 'Karl Kognition C404') AS KT ON c.DataID = KT.[KEY]
LEFT JOIN #Weight cw ON c.DetailID = cw.DetailID
GROUP BY c.PlayerID
)
SELECT rc.Rnk,
...
I'm using a temporary table here for evidence of concept. I am considering adding a column Weights to the table Details to avoid an unnecessary table and left join.
Given that the total number of rows returned by this query below must equal the number of rows in the Invoices table
SELECT VendorName, InvoiceNumber
FROM Invoices
LEFT JOIN Vendors ON Invoices.VendorsID = Vendors.VendorID
Why doesn't the total number of rows returned by this query equal the number of rows in the Vendors table when you replace LEFT keyword with RIGHT keyword?
Your vendors table is the dependent table in a 1-to-Many relationship, so when you execute a RIGHT join on Invoices and Vendors, you will get 1 row for every Invoice + Vendor combination in the relationship, plus 1 row for every Vendor that does not have an invoice record in the Invoices table.
So, Let's say you have three vendors, and among them there are three invoices.
Vendor 1 has 2 invoices
Vendor 2 has 1 invoice
Vendor 3 has 0 invoices
With this data, a RIGHT JOIN will return 4 rows: two rows for Vendor 1, one row for Vendor 2, and 1 row for Vendor 3.
This fiddle provides an example of what I've described above.
The simple answer is because it would mean every record on the "right" side (in this case Vendors) would be represented in the results.
So if you have a vendor which does not have any invoices, it will show in the RIGHT JOIN, but will not show in the LEFT JOIN (because there is no match on the "left" side table).
The right join ensures that all the rows from the right table are present in the results.
But if there are 3 invoices for the same vendor than you still get 3 rows in the result set, not 1. That's how joins work :)
I have the following DB Tables with SQL Server
Booking(bookingID,customerName,branchID,RefNumber,...)
Trip(TripID,vehicleID,...)
BookingToTripMap(TripID,bookingID)
Branch(branchID, branchName)
Vehicle(vehicleID,vehicleNumber)
There is a one to one relationship between (Booking,Branch) and (Trip, Vehicle) and Many to many relationship between Booking, Trip which is saved in the table BookingToTripMap.
Now I want to extract a query that would return the following
Booking.RefNumber Booking.CustomerName Vehicle.VehicleNumber
(All vehicle numbers in one cell)
Here is your query
SELECT B.RefNumber, B.CustomerName, V.VehicleNumber
FROM ((Booking AS B INNER JOIN BookingToTripMap AS BT
ON B.bookingID = BT.bookingID) INNER JOIN TRIP as T
ON T.TripID = BT.TripID) INNER JOIN Vehicle as V
ON V.vehicleID = T.vehicleID
I would add the field bookingID to the table Trip, it seems that the table BookingToTripMap doesn't add any value to your database.
Also, if your vehicle's numbers are unique, you could change the primary key in the Vehicle table to vehicleNumber, and change the same columns in the Trip table. Thus you could retrieve the vehicleNumber directly from the Trip table.
I'm just guessing in that, based on the given information.
Regards,
I'm reading a book, where the author talks about fetching an row + all linked parent rows in one step. Like fetching an order + all it's items all at once. Okay, sounds nice, but really: I've never seen an possibility in SQL to ask for - lets say - one order + 100 items? How would this record set look like? Would I get 101 rows with merged fields of both the order and the item table, where 100 rows have a lot of NULL values for the order fields, while one row has a lot of NULL values for the item fields? Is that the way to go? Or is there something much cooler? I mean... I never heard of fetching arrays onto a field?
A simple JOIN would do the trick:
SELECT o.*
, i.*
FROM orders o
INNER JOIN order_items i
ON o.id = i.order_id
The will return one row for each row in order_items. The returned rows consist of all fields from the orders table, and concatenated to that, all fields from the order_items table (quite literally, the records from the tables are joined, that is, they are combined by record concatenation)
So if orders has (id, order_date, customer_id) and order_items has (order_id, product_id, price) the result of the statement above will consist of records with (id, order_date, customer_id, order_id, product_id, price)
One thing you need to be aware of is that this approach breaks down whenever there are two distinct 'detail' tables for one 'master'. Let me explain.
In the orders/order_items example, orders is the master and order_items is the detail: each row in order_items belongs to, or is dependent on exactly one row in orders. The reverse is not true: one row in the orders table can have zero or more related rows in the order_items table. The join condition
ON o.id = i.order_id
ensures that only related rows are combined and returned (leaving out the condition would retturn all possible combinations of rows from the two tables, assuming the database would allow you to omit the join condition)
Now, suppose you have one master with two details, for example, customers as master and customer_orders as detail1 and customer_phone_numbers. Suppose you want to retrieve a particular customer along with all is orders and all its phone numbers. You might be tempted to write:
SELECT c.*, o.*, p.*
FROM customers c
INNER JOIN customer_orders o
ON c.id = o.customer_id
INNER JOIN customer_phone_numbers p
ON c.id = p.customer_id
This is valid SQL, and it will execute (asuming the tables and column names are in place)
But the problem is, is that it will give you a rubbish result. Assuming you have on customer with two orders (1,2) and two phone numbers (A, B) you get these records:
customer-data | order 1 | phone A
customer-data | order 2 | phone A
customer-data | order 1 | phone B
customer-data | order 2 | phone B
This is rubbish, as it suggests there is some relationship between order 1 and phone numbers A and B and order 2 and phone numbers A and B.
What's worse is that these results can completely explode in numbers of records, much to the detriment of database performance.
So, JOIN is excellent to "flatten" a hierarchy of items of known depth (customer -> orders -> order_items) into one big table which only duplicates the master items for each detail item. But it is awful to extract a true graph of related items. This is a direct consequence of the way SQL is designed - it can only output normalized tables without repeating groups. This is way object relational mappers exist, to allow object definitions that can have multiple dependent collections of subordinate objects to be stored and retrieved from a relational database without losing your sanity as a programmer.
This is normally done through a JOIN clause. This will not result in many NULL values, but many repeated values for the parent row.
Another option, if your database and programming language support it, it to return both result sets in one connection - one select for the parent row another for the related rows.