Programming

FIND_IN_SET () 대 IN ()

procodes 2020. 7. 14. 21:44
반응형

FIND_IN_SET () 대 IN ()


데이터베이스에 2 개의 테이블이 있습니다. 하나는 주문을위한 것이고 다른 하나는 회사를위한 것입니다.

주문의 구조는 다음과 같습니다.

OrderID     |     attachedCompanyIDs
------------------------------------
   1                     1,2,3
   2                     2,4

그리고 회사는 다음과 같은 구조를 가지고 있습니다 :

CompanyID      |        name
--------------------------------------
    1                 Company 1
    2                 Another Company
    3                 StackOverflow
    4                 Nothing

주문 회사 이름을 얻기 위해 다음과 같은 쿼리를 수행 할 수 있습니다.

SELECT name FROM orders,company
WHERE orderID = 1 AND FIND_IN_SET(companyID, attachedCompanyIDs)

해당 쿼리는 제대로 작동하지만 다음 쿼리는 작동하지 않습니다.

SELECT name FROM orders,company
WHERE orderID = 1 AND companyID IN (attachedCompanyIDs)

첫 번째 쿼리는 왜 작동하지만 두 번째 쿼리는 작동하지 않습니까?

첫 번째 쿼리는 다음을 반환합니다.

name
---------------
Company 1
Another Company
StackOverflow

두 번째 쿼리는 다음 만 반환합니다.

name
---------------
Company 1

왜 이것이 첫 번째 쿼리가 모든 회사를 반환하지만 두 번째 쿼리는 첫 번째 쿼리 만 반환합니까?


SELECT  name
FROM    orders,company
WHERE   orderID = 1
        AND companyID IN (attachedCompanyIDs)

attachedCompanyIDsINT(유형 companyID) 으로 캐스팅 된 스칼라 값입니다 .

캐스트는 숫자가 아닌 첫 번째 숫자까지만 숫자를 반환합니다 (귀하의 경우 쉼표).

그러므로,

companyID IN ('1,2,3') ≡ companyID IN (CAST('1,2,3' AS INT)) ≡ companyID IN (1)

에서 PostgreSQL, 당신은 배열에 문자열을 주조 (또는 처음부터 배열로 저장) 수 :

SELECT  name
FROM    orders
JOIN    company
ON      companyID = ANY (('{' | attachedCompanyIDs | '}')::INT[])
WHERE   orderID = 1

그리고 이것도 인덱스를 사용합니다 companyID.

불행히도 MySQL후자는 배열을 지원하지 않기 때문에 작동 하지 않습니다.

이 기사가 흥미로울 수 있습니다 (참조 #2).

최신 정보:

쉼표로 구분 된 목록 (예 :) 이하의 값 수에 대한 합리적인 제한 5이있는 경우이 쿼리를 사용해보십시오.

SELECT  name
FROM    orders
CROSS JOIN
        (
        SELECT  1 AS pos
        UNION ALL
        SELECT  2 AS pos
        UNION ALL
        SELECT  3 AS pos
        UNION ALL
        SELECT  4 AS pos
        UNION ALL
        SELECT  5 AS pos
        ) q
JOIN    company
ON      companyID = CAST(NULLIF(SUBSTRING_INDEX(attachedCompanyIDs, ',', -pos), SUBSTRING_INDEX(attachedCompanyIDs, ',', 1 - pos)) AS UNSIGNED)

attachedCompanyIDs는 하나의 큰 문자열이므로 mysql은 정수로 캐스팅 된 회사를 찾으려고합니다.

어디에서 사용할 때

따라서 comapnyid = 1 인 경우 :

companyID IN ('1,2,3')

이것은 사실이다

그러나 숫자 1이 처음이 아닌 경우

 companyID IN ('2,3,1')

그 반환 거짓


특정 ID를 기반으로하지 않고 모든 관련 회사 이름을 가져옵니다.

SELECT 
    (SELECT GROUP_CONCAT(cmp.cmpny_name) 
    FROM company cmp 
    WHERE FIND_IN_SET(cmp.CompanyID, odr.attachedCompanyIDs)
    ) AS COMPANIES
FROM orders odr

두 번째 쿼리는 id가 1 또는 2 OR 3 인 행을 찾기 때문에 첫 번째 쿼리는 companyID에 존재하는 쉼표로 구분 된 값 중 하나를 찾고 있습니다.

and another problem here is you aren't joining the tables on a common key in your where so you are going to get a mutation of rows that = count(table1) * count(table2);

Your problem really exists with part 2 of my answer. (with your second query)


Let me explain when to use FIND_IN_SET and When to use IN.

Let's take table A which has columns named "aid","aname". Let's take table B which has columns named "bid","bname","aids".

Now there are dummy values in Table A and Table B as below.

Table A

aid aname

1 Apple

2 Banana

3 Mango

Table B

bid bname aids

1 Apple 1,2

2 Banana 2,1

3 Mango 3,1,2

enter code here

Case1: if you want to get those records from table b which has 1 value present in aids columns then you have to use FIND_IN_SET.

Query: select * from A JOIN B ON FIND_IN_SET(A.aid,b.aids) where A.aid = 1 ;

Case2: if you want to get those records from table a which has 1 OR 2 OR 3 value present in aid columns then you have to use IN.

Query: select * from A JOIN B ON A.aid IN (b.aids);

Now here upto you that what you needs through mysql query.


SELECT o.*, GROUP_CONCAT(c.name) FROM Orders AS o , Company.c
    WHERE FIND_IN_SET(c.CompanyID , o.attachedCompanyIDs) GROUP BY o.attachedCompanyIDs

참고URL : https://stackoverflow.com/questions/4155873/find-in-set-vs-in

반응형