MS Access SQL – 如何根据同一表中的另一列连接表

huangapple go评论68阅读模式
英文:

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_SKUMASTER_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.

huangapple
  • 本文由 发表于 2023年6月9日 01:50:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76434492.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定