MySQL - วิธีตรวจสอบค่าในคอลัมน์ทั้งหมด


11

ฉันอยากรู้อยากเห็นมีวิธีที่ดีในการค้นหาคอลัมน์ทั้งหมดสำหรับค่าที่กำหนดหรือไม่ สำหรับจุดประสงค์ของฉันมันไม่จำเป็นต้องรวดเร็วเลยมันเป็นเพียงแค่จุดเดียว 1 จุดและฉันไม่ต้องการพิมพ์ชื่อเขตทุกชื่อ นั่นคือสิ่งที่ฉันจะทำตอนนี้ แต่ฉันคิดว่าแน่นอนว่ามีวิธีที่ดีกว่า

ฉันต้องการที่จะเปิดนี้:

SELECT * FROM table WHERE col1 = 'val' OR col2 = 'val' OR col3 = 'val';

เป็นนี้

SELECT * FROM table WHERE * = 'val'

... หรือดีกว่า (แม้ว่าฉันจะสงสัยอย่างจริงจัง ... )

SELECT * FROM table WHERE * like '%val%'

ฉันพบสิ่งนี้ซึ่งดูเหมือนจะไม่ค่อยดี แต่ฉันไม่พบอะไรที่ใกล้เคียงกว่านี้:

SELECT whatever WHERE col1,col2 IN ((val1, val2), (val1, val2), ...)

ความแตกต่างคือการค้นหาคอลัมน์ที่เลือกค่าที่ระบุในขณะที่ฉันพยายามค้นหาคอลัมน์ทั้งหมดสำหรับค่าเดียว

มันไม่สำคัญเหมือนที่ฉันพูดมากกว่าสิ่งที่ฉันแค่อยากรู้

คำตอบ:


23

SQL ไม่ได้มีวิธีที่ดีในการทำเช่นนี้เพราะมันอาจไม่ใช่การออกแบบตารางที่ดีที่จะมีคอลัมน์ N ที่อาจมีค่าในโดเมนเดียวกัน นี้อาจเป็นกรณีของ "กลุ่มซ้ำ" เช่นถ้าคุณมีคอลัมน์phone1, phone2, ...phone3phoneN

หากคุณมีคอลัมน์จำนวนมากที่มีโดเมนแบบโลจิคัลค่าเดียวกันอาจเป็นกรณีที่เป็นแอตทริบิวต์ที่มีมูลค่าหลายมูลค่า (เช่นตัวอย่างโทรศัพท์) วิธีมาตรฐานของการจัดเก็บแอตทริบิวต์ที่มีค่าหลาย ๆ ค่านั้นมีหลายแถวในตารางอื่นโดยมีการอ้างอิงไปยังแถวที่อยู่ในตารางหลัก

หากคุณทำเช่นนั้นคุณจะต้องค้นหาค่าเฉพาะในหนึ่งคอลัมน์ของตารางที่ขึ้นต่อกัน

SELECT t.* FROM mytable AS t
JOIN phones AS p ON t.primaryKey = p.refKey 
WHERE p.phone = ?

1
และถ้าด้วยเหตุผลใดก็ตามที่คุณไม่สามารถเปลี่ยนเค้าโครงตารางคุณสามารถเขียนมุมมองที่แสดงถึงข้อมูลในรูปแบบนี้จากนั้นสอบถามมุมมอง
CodeCaster

10
ไม่เพียงแค่เปลี่ยนเค้าโครงตาราง แค่นั้นแหละ. ฉันเบื่อกับข้อแก้ตัว "ฉันเปลี่ยนมันไม่ได้" ฉันไม่ยอมรับอีกต่อไป ถึงเวลาที่จะเรียนรู้วิธีการเปลี่ยนแปลงสิ่งต่าง ๆ
Bill Karwin

15

ยิ่งคุณเข้าใกล้ได้มากเท่าไรคุณก็จะได้IN:

SELECT * FROM table WHERE 'val' IN (col1, col2, ..., colN) ;

คุณยังต้องเขียนคอลัมน์ทั้งหมดที่คุณต้องการตรวจสอบ
และมันก็ไม่ต่างไปจากORนิพจน์ที่คุณมีไม่ใช่ในการแสดงหรืออื่น ๆ นี่เป็นวิธีที่แตกต่างและเทียบเท่าในการเขียนนิพจน์โดยมีอักขระน้อยลงเล็กน้อย


3

คุณต้องทำในสองขั้นตอนแรกสร้าง sql like (สมมติว่าตารางของคุณชื่อ T ใน schema S:

select concat(' SELECT * FROM t WHERE ''a'' in ('
             , GROUP_CONCAT(COLUMN_NAME)
             , ')')
from INFORMATION_SCHEMA.columns 
where table_schema = 's' 
  and table_name = 't'
  and DATA_TYPE IN ('char','varchar');

ตอนนี้คุณสามารถรันสตริงนี้ โปรดทราบว่าคุณต้องพูด 'a' ด้วยส่วนเสริมพิเศษ หากคุณใส่ไว้ในขั้นตอนตัวอย่างคุณสามารถจัดเตรียมและดำเนินการกับสตริงที่สร้างขึ้น

ฉันทดสอบด้วย:

create table t (a char(3), b varchar(5), c int);
insert into t(a,b) values ('a','b'),('b','c'),('c','c');    

แบบสอบถามสร้างขึ้นที่:

SELECT * FROM t WHERE 'a' in (a,b)

และเรียกใช้งานผลลัพธ์นั้น:

a   b   c
---------
a   b   

1

รู้สึกเหมือนเป็นเวลาหนึ่งปีแล้วที่ฉันถามสิ่งนี้ แต่ฉันเพิ่งสะดุดกับสิ่งที่ดูเหมือนจะเป็นสิ่งที่ฉันกำลังมองหา! ไม่ใช่คำสั่ง SQL เหมือนที่ฉันคาดไว้ แต่ก็เป็นสิ่งที่ฉันต้องการ

ใน MySQL Workbench คุณสามารถคลิกขวาที่ตารางหรือสคีมาแล้วเลือกข้อมูลตารางการค้นหาเมนูบริบทสคีมา


0

ลองอันนี้:

select
    *
from
    _table_
where
    concat('.', col1, '.', col2, '.', col3, '.') like "%.search_value.%";

สิ่งนี้จะถือว่าไม่มี.ในสตริงการค้นหาของคุณ หากคุณไม่สามารถรับประกันได้คุณอาจใช้“ ตัวคั่น” อื่น


1
คุณช่วยอธิบายได้ไหมว่าทำไมโซลูชันของคุณถึงได้ผลโปรด คำตอบของโค้ดไม่ได้ถูกมองว่าเป็นคำตอบที่ดีที่นี่
George.Palacios

มันไม่ทำงาน เช่นหากการค้นหาประกอบด้วย%หรือ_หรือคอลัมน์ใด ๆ ที่มี.
Jasen

1
@Jasen คุณสามารถหลีกเลี่ยงอักขระพิเศษและใช้ตัวคั่นอื่น
Anon0012398193

@ George.Palacios - อะไรที่คุณไม่ชัดเจน?
Anon0012398193

การเลือกตัวคั่นที่ถูกต้องอาจเป็นเรื่องยากมาก วิธีนี้ยากมากที่จะทำสิ่งที่ถูกต้อง
Jasen

0

ทางออกที่ง่ายที่สุดคือการทำ

mysqldump ... --skip-extended-insert db table | grep 'val'

เว้นแต่วาลเป็นสิ่งที่เกิดขึ้นทั่วไปในไวยากรณ์ SQL


ฉันหวังว่าคุณจะเยาะเย้ยฉันเป็นทางเลือกคือคุณคิดว่านี่จะเป็นประโยชน์
donutguy640

1
ฉันไม่แน่นอน มันเป็นวิธีที่ถูกต้องในการค้นหาสิ่งที่ถ้าคุณไม่ทราบว่า "ที่ไหน" มันอยู่ใน db / ตาราง grep จะส่งคืนแถวทั้งหมด (รวมถึงชื่อตาราง) ที่มีค่าอยู่ ไม่ใช่ SQL และไม่มีประโยชน์หากคุณต้องการประมวลผลเอาต์พุตโดยทางโปรแกรม แต่มันง่ายและรวดเร็วมาก
jkavalik

-2

ลองสิ่งนี้

SELECT *
FROM table
WHERE CONCAT(col1,' ',col2,' ',col3)="val val val";

CONCAT () ใช้เพื่อแยกค่าคอลัมน์เช่นเดียวกับที่นี่คุณสามารถแยกคอลัมน์ของคุณด้วยช่องว่างเพื่อระบุผลลัพธ์ที่ดีกว่าภายในฟังก์ชั่นและตรวจสอบค่าสตริงที่คั่นด้วยช่องว่างและผลลัพธ์อยู่ในมือของคุณ


-3

เป็นไปได้โดยใช้ฐานข้อมูล information_schema โดยทั่วไปแล้วเราจะแสดงรายการคอลัมน์ทั้งหมดของตารางเฉพาะจากนั้นใช้ GROUP_CONCAT เพื่อแสดงรายการเป็นหนึ่งบรรทัดจากนั้นป้อนเข้าในคำสั่ง IN

select * from db.table where 'value' in (select GROUP_CONCAT(COLUMN_NAME) from INFORMATION_SCHEMA.columns where table_schema = 'db' and table_name = 'table');

นี่จะส่งคืนแถวหากมี 'ค่า' อยู่ในคอลัมน์ทั้งหมดเท่านั้น


1
คุณหมายถึงif 'value' is present in any of the columnsอะไร นอกจากนี้คุณสามารถเพิ่มภาคแสดงสำหรับประเภทสตริงเช่น: `และ DATA_TYPE IN ('char', 'varchar')`
Lennart

1
สิ่งนี้จะทำและบรรลุเป้าหมายของ OP ในการหลีกเลี่ยงการตั้งชื่อคอลัมน์อย่างชัดเจน ไม่ใช่ wildcard แต่ GROUP_CONCAT กับ schema ของข้อมูลนั้นดีเท่ากับ wildcard ของชื่อคอลัมน์ทั้งหมด
tbrookside

2
ฉันมีปัญหาในการทำให้สิ่งนี้ทำงานได้ ฉันแทนที่ฐานข้อมูลและตารางด้วยชื่อสคีมาและตารางของฉันมีอะไรอีกที่ตั้งใจจะเป็นตัวแทนสำหรับชื่อจริงหรือไม่? นอกจากนี้ฉันลองคำสั่งภายในด้วยตัวเองและฉันรู้ว่ามัน CONCATs ชื่อคอลัมน์มากกว่าข้อมูลของแถว นั่นคือสิ่งที่คุณตั้งใจหรือไม่
donutguy640

4
ด้วยความเคารพเนื่องจากทั้งหมดนี้เป็นสิ่งที่ผิด การค้นหาของคุณจะเปรียบเทียบ 'ค่า' กับชื่อคอลัมน์ของพวกเขาไม่ได้เนื้อหา ฉันต้องให้ downvote นี้
Bill Karwin

4
ถูกต้องมากขึ้นนี้จะเปรียบเทียบสตริง 'ค่า' เพื่อสตริงที่เป็นรายการที่คั่นด้วยเครื่องหมายจุลภาคชื่อคอลัมน์ - where 'value' in ('col1,col2,col3…')หลักเช่นเดียวกับ
Andriy M
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.