英文:
MS Access SQL - how to join table based on another column in the same table
问题
在我的数据库中,我们有一个名为MASTER_SKU_DATA的表,其中包括SKU、描述和Deposit_SKU(这是另一个SKU,在同一个MASTER_SKU_DATA表中有其自己的记录)
我们可能有一个示例SKU为12345,供应商ID为999,以及一个存款SKU为10001。存款SKU通常会有不同的供应商,因此我想创建一个查询,该查询将连接表格并提供其他供应商ID(并且还要连接一个定价表)
来自MASTER_SKU_DATA表的示例数据集:
(SKUP是原始数据库表,MASTER_SKU_DATA用于连接其他字段,如供应商名称,以便轻松访问相关信息)
SKU | Description | Deposit SKU | Supplier ID |
---|---|---|---|
12345 | 项目编号1 | 10001 | 999 |
67890 | 项目编号2(无需存款) | 999 | |
10001 | 存款SKU 1 | 914851 |
来自MASTER_PRICE_COST表的示例:
SKU | PRICE_START_DATE | PRICE_END_DATE | PRICE |
---|---|---|---|
12345 | 2023年1月1日 | 2100年5月31日 | 50 |
12345 | 2023年6月1日 | 2100年12月31日 | 51 |
67890 | 2023年1月1日 | 2100年12月31日 | 42 |
10001 | 2023年1月1日 | 2100年12月31日 | 30 |
示例结果:
Deposit SKU | Description | Supplier ID | PRICE_START_DATE | PRICE_END_DATE | PRICE |
---|---|---|---|---|---|
10001 | 存款SKU 1 | 914851 | 2023年1月1日 | 2100年12月31日 | 30 |
我创建了一个名为[DepositSKUs]的非常简单的查询,该查询使用以下查询:
SELECT DISTINCT SKUP.DEPOSIT_SKU FROM SKUP WHERE (SKUP.DEPOSIT_SKU Is Not Null)
现在,我正在尝试运行另一个查询,该查询将连接我们的MASTER_PRICE_COST,但仅在MASTER_SKU_DATA是这些Deposit_SKUs之一时才会运行。我使用以下查询:
SELECT MASTER_SKU_DATA.SKU,
MASTER_SKU_DATA.Description,
MASTER_SKU_DATA.Active_Flag,
MASTER_SKU_DATA.ID_Supplier,
MASTER_SKU_DATA.Supplier_Name,
MASTER_PRICE_COST.PRICE_START_DATE,
MASTER_PRICE_COST.PRICE_END_DATE,
MASTER_PRICE_COST.PRICE
FROM MASTER_SKU_DATA
LEFT JOIN MASTER_PRICE_COST ON
MASTER_SKU_DATA.SKU = MASTER_PRICE_COST.SKU
WHERE MASTER_SKU_DATA.SKU IN (SELECT DepositSKUs.DEPOSIT_SKU FROM DepositSKUs)
但是,当我尝试运行此查询时,它会冻结我的Microsoft Access,并且似乎无法正常工作,我不知道原因。
我一直在尝试研究这个问题,发现一些提示,表明当您使用一个值在此列表中时,它会占用更多的处理能力,因为它会检查每个SKU是否等于
但是,我无法找到任何解决方案,说明如何通过JOIN来执行相同的筛选。
我尝试了一些测试,例如将MASTER_SKU_DATA作为[DEP_SKUD]加入,但似乎无法正确使用语法,也不知道要进一步查找什么。
您能告诉我是否有办法修复此查询吗?
如果有不同的功能或特性,我可以进行Google和进一步研究,请告诉我 - 只是被卡住了,不知道自己错在哪里。
英文:
In my database, we have a MASTER_SKU_DATA table, which includes the SKU, Description, and Deposit_SKU (which is another SKU, with its own record in the same MASTER_SKU_DATA table)
We may have an example SKU of 12345, with supplier ID 999, and a deposit SKU of 10001. The Deposit SKU normally will have a different supplier, so I want to create a query which will join the table back onto itself to provide the other Supplier ID (and join a pricing table as well)
An example set of data from the MASTER_SKU_DATA table:
(SKUP is the original database table, MASTER_SKU_DATA helps to join a few other fields such as Supplier Name for easy access to related information)
SKU | Description | Deposit SKU | Supplier ID |
---|---|---|---|
12345 | Item number 1 | 10001 | 999 |
67890 | Item number 2 (no deposit needed) | 999 | |
10001 | DEPOSIT SKU 1 | 914851 |
Example from MASTER_PRICE_COST table:
SKU | PRICE_START_DATE | PRICE_END_DATE | PRICE |
---|---|---|---|
12345 | 1/1/2023 | 5/31/2023 | 50 |
12345 | 6/1/2023 | 12/31/2100 | 51 |
67890 | 1/1/2023 | 12/31/2100 | 42 |
10001 | 1/1/2023 | 12/31/2100 | 30 |
Example result:
Deposit SKU | Description | Supplier ID | PRICE_START_DATE | PRICE_END_DATE | PRICE |
---|---|---|---|---|---|
10001 | DEPOSIT SKU 1 | 914851 | 1/1/2023 | 12/31/2100 | 30 |
I created a very simple query called [DepositSKUs], which uses this query:
SELECT DISTINCT SKUP.DEPOSIT_SKU FROM SKUP WHERE (SKUP.DEPOSIT_SKU Is Not Null)
Now I'm trying to run another query of the MASTER_SKU_DATA, joining our MASTER_PRICE_COST as well, but only where the MASTER_SKU_DATA is one of those Deposit_SKUs. I'm using the query below:
SELECT MASTER_SKU_DATA.SKU,
MASTER_SKU_DATA.Description,
MASTER_SKU_DATA.Active_Flag,
MASTER_SKU_DATA.ID_Supplier,
MASTER_SKU_DATA.Supplier_Name,
MASTER_PRICE_COST.PRICE_START_DATE,
MASTER_PRICE_COST.PRICE_END_DATE,
MASTER_PRICE_COST.PRICE
FROM MASTER_SKU_DATA
LEFT JOIN MASTER_PRICE_COST ON
MASTER_SKU_DATA.SKU = MASTER_PRICE_COST.SKU
WHERE MASTER_SKU_DATA.SKU IN (SELECT DepositSKUs.DEPOSIT_SKU FROM DepositSKUs)
However, when I try to run this query, it keeps freezing my Microsoft Access, and doesn't seem to work properly and I'm not sure why.
I've been trying to research this and found some tips, indicating that when you use a query where a value is IN this list, it takes more processing power because it's checking for each SKU if SKU = <value1> OR SKU = <value2> etc..
I couldn't find any solutions however, on how to do this same filter through the JOIN instead.
I've tried to test things such as joining the MASTER_SKU_DATA AS [DEP_SKUD], but can't seem to get the syntax right and I'm not sure where to look further.
Could you please let me know if there is a way I could fix this query?
If there is a different function or feature which I can google and research further, please let me know - just stumped and not sure where I'm steering wrong.
答案1
得分: 2
看起来你正在过度思考解决方案。我假设SKU是主键,因此永远不会有空值。尝试这个SQL,我已经通过Deposit_SKU
将MASTER_SKU_DATA
与自身连接:
SELECT MASTER_SKU_DATA.Deposit_SKU,
MASTER_SKU_DATA_1.Description,
MASTER_SKU_DATA_1.ID_Supplier,
MASTER_PRICE_COST.PRICE_START_DATE,
MASTER_PRICE_COST.PRICE_END_DATE,
MASTER_PRICE_COST.Price
FROM MASTER_SKU_DATA
INNER JOIN (
MASTER_SKU_DATA AS MASTER_SKU_DATA_1
INNER JOIN MASTER_PRICE_COST
ON MASTER_SKU_DATA_1.SKU = MASTER_PRICE_COST.SKU
)
ON MASTER_SKU_DATA.Deposit_SKU = MASTER_SKU_DATA_1.SKU;
根据你提供的数据,它会生成你也提供的示例结果。
英文:
It looks like you're trying to overthink the solution. I am assuming that SKU is the primary key so you will never have a null value. Try this SQL where I have joined MASTER_SKU_DATA
to itself via the Deposit_SKU
:
SELECT MASTER_SKU_DATA.Deposit_SKU,
MASTER_SKU_DATA_1.Description,
MASTER_SKU_DATA_1.ID_Supplier,
MASTER_PRICE_COST.PRICE_START_DATE,
MASTER_PRICE_COST.PRICE_END_DATE,
MASTER_PRICE_COST.Price
FROM MASTER_SKU_DATA
INNER JOIN (
MASTER_SKU_DATA AS MASTER_SKU_DATA_1
INNER JOIN MASTER_PRICE_COST
ON MASTER_SKU_DATA_1.SKU = MASTER_PRICE_COST.SKU
)
ON MASTER_SKU_DATA.Deposit_SKU = MASTER_SKU_DATA_1.SKU;
Based on the data you provided, it produces the example result that you also provided.
答案2
得分: 1
您尝试做的是一种称为自关联连接的操作。这是两个相同表的实例之间的连接,其中一个实例的外键引用另一个实例的主键。如果您对自关联连接进行一些研究,您应该能够找到教程。不幸的是,当我进行搜索时,弹出的示例都不涉及MS ACCESS,而是针对其他DBMS。
以下是我尝试(未经调试)提供的一条查询,以实现您的需求:
SELECT
M.Deposit_SKU,
S.Description,
S.Supplier_ID,
P.PRICE_START_DATE,
P.PRICE_END_DATE,
P.PRICE
FROM (
MASTER_SKU_DATA S
INNER JOIN MASTER_SKU_DATA M
ON S.SKU = M.Deposit_SKU)
INNER JOIN MASTER_PRICE_COST P
ON S.SKU = P.SKU
这里有几点需要注意:
Deposit_SKU 字段可能包含三种类型的值。它可能包含 NULL,也可能包含有效值,或者可能包含无效值。无效值是指没有与匹配的 SKU 相对应的记录的情况。这可能是数据出现问题的线索。此查询将会排除掉 Deposit_SKU 字段中的 NULL 或无效值的记录。
我选择使用与价格表的 INNER JOIN 而不是您选择的 LEFT JOIN。我的选择可能不正确,如果主表中有一些 SKU 在价格表中没有条目的情况下。通常情况下,使用 INNER JOIN 会稍微快一些,因为它会产生正确的结果。
通常情况下,自关联连接需要使用表别名。我使用了单个字母的表别名。这是我的习惯,您可以根据需要进行调整。
我选择选择 M.Deposit_SKU 而不是 S.SKU,以使输出中的列标题与您的示例匹配。
英文:
What you are trying to do is known as a reflexive join. This is a join between two instances of the same table, where a foreign key of one instance references the primary key of the other instance. If you do some research on reflexive joins, you should get a tutorial. Unfortunately, when I did the search, none of the examples that popped up were cases that involved MS ACCESS. They were all for some other DBMS.
Here is my attempt (not debugged) to provide a single query to do what you want:
SELECT
M.Deposit_SKU,
S.Description,
S.Supplier_ID,
P.PRICE_START_DATE,
P.PRICE_END_DATE,
P.PRICE
FROM (
MASTER_SKU_DATA S
INNER JOIN MASTER_SKU_DATA M
ON S.SKU = M.Deposit_SKU)
INNER JOIN MASTER_PRICE_COST P
ON S.SKU = P.SKU
There are several points to be noted here.
The Deposit_SKU field could contain three kinds of value. It could contain a NULL, or it could contain a valid value, or it could contain an invalid value. An invalid value would be one where there is no corresponding record with a matching SKU. That would be a clue that the data is messed up, somehow. This query will drop out records with a NULL or an invalid value in the Deposit_SKU field.
I chose to use an INNER JOIN with the price table instead of the LEFT JOIN you chose. My choice could be incorrect, if there are some SKUs in the master table with no entry in the price table. It is generally a little faster to use INNER JOIN, when it produces correct results.
In general, reflexive joins can't be done without table aliases. I used one letter abbreviations for table aliases. That's my habit. Suit yourself.
I chose to select M.Deposit_SKU instead of S.SKU so that the column header in the output would match your example.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论