I usually perform a JOIN between two tables using a common column, in this case 'product_code'.
Now comes this query that does it without a join:
SELECT `rp_products`.`product_code`, `rp_log`.`customer_id`, `rp_products`.`product_name`
FROM rp_products, rp_log
WHERE (`rp_log`.`customer_id` = '111')
ORDER BY `rp_products`.`product_code` ASC, `rp_log`.`customer_id` ASC
That returns:
product_code customer_id product_name
105 111 Paintballs 2000PBS
105 111 Paintballs 2000PBS
106 111 Gloves
106 111 Gloves
What I want to know, is how is it showing the correct 'product_name' without joining the 'product_code' between the tables? product_code is not a primary key or anything like that. product_name is the name of both columns in the tables.
rp_log stores the customer_id, product_code, and date of purchase (not shown here).
rp_products stores product_code, price (not shown here) and product_name.
Thank for for your time,
Evan.
You're performing a cross product of the entire rp_products table and the sub-table of rp_log which has a customer_id of 111. I'd guess that you have two 111 entries in rp_log and two entries in rp_products; then each entry in each table (or sub-table) in the join will be pair with each entry in the other to produce the four (= 2 × 2) rows in your result set.
Including more columns from rp_log and rp_products might clarify things for you.
Related
I have the following situation. I have a table with all info of article. I will like to compare the same column with it self. because I have multiple type of article. Single product and Master product. the only way that I have to differences it, is by SKU. for example.
ID | SKU
1 | 11111
2 | 11112
3 | 11113
4 | 11113-5
5 | 11113-8
6 | 11114
7 | 11115
8 | 11115-1-W
9 | 11115-2
10 | 11116
I only want to list or / and count only the sku that are full unique. follow th example the sku that are unique and no have variant are (ID = 1, 2, 6 and 10) I will want to create a query where if 11113 are again on the column not cout it. so in total I will be 4 unique sku and not "6 (on total)". Please let me know. if this are possible.
Assuming the length of master SKUs are 5 characters, try this:
select a.*
from mytable a
left join mytable b on b.sku like concat(a.sku, '%')
where length(a.sku) = 5
and b.sku is null
This query joins master SKUs to child ones, but filters out successful joins - leaving only solitary master SKUs.
You can do this by grouping and counting the unique rows.
First, we will need to take your table and add a new column, MasterSKU. This will be the first five characters of the SKU column. Once we have the MasterSKU, we can then GROUP BY it. This will bundle together all of the rows having the same MasterSKU. Once we are grouping we get access to aggregate functions like COUNT(). We will use that function to count the number of rows for each MasterSKU. Then, we will filter out any rows that have a COUNT() over 1. That will leave you with only the unique rows remaining.
Take that unique list and LEFT JOIN it back into your original table to grab the IDs.
SELECT ID, A.MasterSKU
FROM (
SELECT
MasterSKU = SUBSTRING(SKU,1,5),
MasterSKUCount = COUNT(*)
FROM MyTable
GROUP BY SUBSTRING(SKU,1,5)
HAVING COUNT(*) = 1
) AS A
LEFT JOIN (
SELECT
ID,
MasterSKU = SUBSTRING(SKU,1,5)
FROM MyTable
) AS B
ON A.MasterSKU = B.MasterSKU
Now one thing I noticed from you example. The original SKU column really looks like three columns in one. We have multiple values being joined with hypens.
11115-1-W
There may be a reason for it, but most likely this violates first normal form and will make the database hard to query. It's part of the reason why such a complicated query is needed. If the SKU column really represents multiple things then we may want to consider breaking it out into MasterSKU, Version, and Color or whatever each hyphen represents.
I am trying to query a dataset from a single table, which contains quiz answers/entries from multiple users. I want to pull out the highest scoring entry from each individual user.
My data looks like the following:
ID TP_ID quiz_id name num_questions correct incorrect percent created_at
1 10154312970149546 1 Joe 3 2 1 67 2015-09-20 22:47:10
2 10154312970149546 1 Joe 3 3 0 100 2015-09-21 20:15:20
3 125564674465289 1 Test User 3 1 2 33 2015-09-23 08:07:18
4 10153627558393996 1 Bob 3 3 0 100 2015-09-23 11:27:02
My query looks like the following:
SELECT * FROM `entries`
WHERE `TP_ID` IN('10153627558393996', '10154312970149546')
GROUP BY `TP_ID`
ORDER BY `correct` DESC
In my mind, what that should do is get the two users from the IN clause, order them by the number of correct answers and then group them together, so I should be left with the 2 highest scores from those two users.
In reality it's giving me two results, but the one from Joe gives me the lower of the two values (2), with Bob first with a score of 3. Swapping to ASC ordering keeps the scores the same but places Joe first.
So, how could I achieve what I need?
You're after the groupwise maximum, which can be obtained by joining the grouped results back to the table:
SELECT * FROM entries NATURAL JOIN (
SELECT TP_ID, MAX(correct) correct
FROM entries
WHERE TP_ID IN ('10153627558393996', '10154312970149546')
GROUP BY TP_ID
) t
Of course, if a user has multiple records with the maximal score, it will return all of them; should you only want some subset, you'll need to express the logic for determining which.
MySql is quite lax when it comes to group-by-clauses - but as a rule of thumb you should try to follow the rule that other DBMSs enforce:
In a group-by-query each column should either be part of the group-by-clause or contain a column-function.
For your query I would suggest:
SELECT `TP_ID`,`name`,max(`correct`) FROM `entries`
WHERE `TP_ID` IN('10153627558393996', '10154312970149546')
GROUP BY `TP_ID`,`name`
Since your table seems quite denormalized the group by name-par could be omitted, but it might be necessary in other cases.
ORDER BY is only used to specify in which order the results are returned but does nothing about what results are returned - so you need to apply the max()-function to get the highest number of right answers.
I am VERY new to SQL and do not know that much about it, but I am a quick learner. I have a database with Item IDs and Quantities on Hand (qoh) along with some other columns that I am not having issues with. The problem is that when I tell it to give me the item id column with the qoh column, it gives me almost 500 rows for each individual item because the qoh is different so I literally have about 12 million rows. Now, what I am looking for is the most recent quantity for each item. I am assuming that this is a one-to-many relationship and since I am below a noobie to SQL, I don't even really know where to begin. This is what I have so far:
SELECT DISTINCT item_id, qty_on_hand
FROM database.inv_mast, database.inv_loc
ORDER BY item_id ASC
Oh and I'm using Microsoft SQL Server Management Studio
Here is what I want:
| item_id |qty_on_hand|
|123456789| 93 |
|456789123| 87 |
|789456123| 74 |
etc.
But what I'm getting is:
| item_id |qty_on_hand|
|123456789| 85 |
|123456789| 82 |
|123456789| 92 |
etc.
I am getting the same item_id at least 4000 times because the database is telling me what the qoh was for literally every second of time since we've had the item. I only want what is in the warehouse at the time of me running the query. I apologize for all the noobness, but I literally don't know SQL.
You are doing a cross join by just using ",". What you need to do is a inner join I think.
SELECT DISTINCT im.item_id, qty_on_hand
FROM database.inv_mast im
INNER JOIN database.inv_loc in on im.item_id = in.item_id
ORDER BY item_id ASC
You also should look at left and right joins.
So in summary using "," is like using a cross join
You really need to learn joins to understand these queries, check out the site below.
http://www.w3schools.com/sql/sql_join.asp
The from clause FROM database.inv_mast, database.inv_loc creates the cartesian product. Narrow that down using a WHERE condition.
Regarding MySQL queries, how can I get all table entries that belong to combinations of entries in another table?
Background: I would like to count orders which consist of order items. Each order item has a state like 'canceled' or 'delivered'. There are partial deliveries, so that there can be both delivered and canceled orders in one order. I would like to count the net orders and I would like to know how many orders have items with more than one item status.
Order Number | Order Item | Status
X0001 | Item | delivered
X0001 | Item | delivered
X0002 | Item | delivered
X0002 | Item | canceled
X0002 | Item | delivered
X0003 | Item | delivered
I have 3 valid orders here and one order with delivered/canceled. How can I ask for all orders which have at least one delivered and one canceled item?
As I am very new to MySQL I am basically looking for the right approach. Do I need subqueries or joints for this?
Edit: First of all, sorry for the late reply. And sorry again because my question was obviously misleading.
There are three tables involved: 'order', 'order_item' and 'order_item_status'.
'order' and 'order_item' are linked through 'order_item.fk_order' and 'order.id_order'.
'order_item' and 'order_item_status' are linked through 'order_item.fk_order_item_status' and 'order_item_status.id_order_item_status'.
You have been very helpful so far but I am still a bit stuck as I do not know how to finally count by combination.
The perfect result would be something like that:
{shipped} | 34
{canceled} | 12
{shipped, canceled} | 8
{closed, canceled} | 4
{closed} | 27
... | ...
But I don't know how to deal with combinations in a query. Maybe you have some more helpful hints for me ...
Thank you very much.
I assume you have two table:
orders (list of your orders)
order_items (list of itemd of order)
two table are relationed by field fk_order.
try this:
SELECT o.id, (select count(*) from order_items i where i.status = 'delivered' and i.fk_order = o.id) as item_delivered, (select count(distinct i.status) from order_items i where i.fk_order = o.id) as status_no
FROM orders o
I assume your data are all in one table like you described. Then you want to group your data by order number and then only get the orders with both canceled and delivered ?
The request should also look like :
select * from table \
group by Order Number \
Having State="canceled" and State="delivered"
By join on the table with the same table you can select rows with different values. Then count the distinct order numbers.
SELECT COUNT(DISTINCT orig.Number)
FROM order_items AS orig
INNER JOIN order_items AS diff ON diff.Number = orig.Number AND diff.Status != orig.Status
This is quicker than using sub-queries.
Edit: Forgot to mention it's a more scalable implementation as well as you can add more order statuses without this failing.
I don't understand why you are talking about "combinations of entries in another table" ?
According to the following of your question you have one single table with - at least - 3 attributes: Order number, Order item, Status. Is that correct or are some of those attributes in another table and in that case can you elaborate ?
Otherwise I would try to use sub-requests and do something like:
SELECT T1.* FROM table T1 WHERE T1.status=canceled AND T1.order_number IN (SELECT T2.order_number FROM table T2 where T2.status=delivered)
I have a very specific query that is acting up and I could use any help at all with debugging it.
There are 4 tables involved in this query.
Transaction_Type
Transaction_ID (primary)
Transaction_amount
Transaction_Type
Transaction
Transaction_ID (primary)
Timestamp
Purchase
Transaction_ID
Item_ID
Item
Item_ID
Client_ID
Lets say there is a transaction in which someone pays $20 in cash and $0 in credit it inserts two rows into the table.
//row 1
Transaction_ID: 1
Transaction_amount: 20.00
Transaction_type: cash
//row 2
Transaction_ID: 1
Transaction_amount: 0.00
Transaction_type: credit
here is the specific query:
SELECT
tt.Transaction_Amount, tt.Transaction_ID
FROM
ItemTracker_dbo.Transaction_Type tt
JOIN
ItemTracker_dbo.Transaction t
ON
tt.Transaction_ID = t.Transaction_ID
JOIN
ItemTracker_dbo.Purchase p
ON
p.Transaction_ID = tt.Transaction_ID
JOIN
ItemTracker_dbo.Item i
ON
i.Item_ID = p.Item_ID
WHERE
t.TimeStamp >= "2010-01-06 00:00:00" AND t.TimeStamp <= "2010-01-06 23:59:59"
AND
tt.Transaction_Format IN ('cash', 'credit')
AND
i.Client_ID = 3
when I execute this query, it returns 4 rows for a specific transaction. (it should be 2)
When I remove ALL where clauses and insert WHERE tt.Transaction_ID = problematicID it only returns two.
EDIT:::::
still repeats upon changing date range
The kicker:
When I change the initial daterange it only returns two rows for that specific transaction_id.
::::
Is it the way I use join? that's all I can think of...
EDIT: This is the problem
in purchase - two sepparate purchase_ID's can have the same transaction_ID (purhcase_ID breaks down specific item sales).
There are duplicate Transaction_ID rows in purchase_ID
We need to see all the data in all the tables to be able to know where the problem is. However, because the joins are the problem it is because one of your tables has two rows when you think it has only one.
There's a problem with your schema. You have rows with the same transaction_id, which is the primary key. I would think they couldn't be marked primary in that database. With two rows with the same id, that could cause unexpected extra rows to come back from the join(s).