MySQL - Cách kiểm tra giá trị trong tất cả các cột


11

Tôi tò mò, có cách nào tốt để tìm kiếm tất cả các cột cho một giá trị nhất định không? Đối với mục đích của tôi, nó không cần phải nhanh chóng, đó chỉ là một việc đơn giản và tôi thực sự không muốn phải gõ mọi tên trường. Đó chính xác là những gì tôi sẽ làm bây giờ, nhưng tôi nghĩ chắc chắn có một cách tốt hơn.

Tôi muốn biến điều này:

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

vào đây:

SELECT * FROM table WHERE * = 'val'

... Hoặc, thậm chí tốt hơn (mặc dù tôi thực sự nghi ngờ về điều đó ...)

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

Tôi đã tìm thấy thứ này , có vẻ như không thực sự gần gũi, nhưng tôi không tìm thấy gì gần hơn:

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

Sự khác biệt là, tìm kiếm một lựa chọn các cột cho các giá trị được chỉ định, trong khi tôi đang cố gắng tìm kiếm TẤT CẢ các cột cho một giá trị.

Mặc dù điều đó không quan trọng, như tôi đã nói nhiều hơn bất cứ điều gì tôi chỉ tò mò

Câu trả lời:


23

SQL không cung cấp một cách tốt để làm điều này bởi vì nó có thể không phải là một thiết kế bảng tốt để có N cột có thể có các giá trị trong cùng một miền. Đây là khả năng một trường hợp "nhóm lặp đi lặp lại" như thế nào nếu bạn có các cột phone1, phone2, phone3, ... phoneN.

Nếu bạn có một số cột có cùng miền giá trị logic, đó có thể là trường hợp thuộc tính đa giá trị (như ví dụ về điện thoại). Cách lưu trữ các thuộc tính đa giá trị tiêu chuẩn là nhiều hàng trong một bảng khác, với tham chiếu đến hàng mà chúng thuộc về trong bảng chính.

Nếu bạn làm điều đó, thì bạn chỉ phải tìm kiếm giá trị cụ thể trong một cột của bảng phụ thuộc.

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

1
Và nếu vì bất kỳ lý do gì bạn không thể thay đổi bố cục bảng, bạn có thể viết chế độ xem đại diện cho dữ liệu ở định dạng này, sau đó truy vấn chế độ xem.
CodeCaster

10
Không, chỉ cần thay đổi cách bố trí bảng. Đó là nó. Tôi mệt mỏi với cái cớ "Tôi không thể thay đổi nó." Tôi không chấp nhận điều đó nữa. Đã đến lúc học cách thay đổi mọi thứ.
Bill Karwin

15

Bạn càng có thể đến gần hơn bằng cách sử dụng IN:

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

Bạn vẫn phải viết tất cả các cột bạn muốn kiểm tra.
Và nó không khác gì ORbiểu hiện bạn có, không phải trong hiệu suất hay cách khác. Đây chỉ là một cách khác nhau, tương đương để viết biểu thức, với ít ký tự hơn một chút.


3

Bạn cần thực hiện theo hai bước, đầu tiên tạo sql like (giả sử bảng của bạn có tên T trong lược đồ 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');

Bây giờ bạn có thể thực hiện chuỗi này. Lưu ý rằng bạn phải trích dẫn 'a' có thêm '. Nếu bạn đặt điều này vào ví dụ một thủ tục, bạn có thể chuẩn bị và thực thi chuỗi đã được tạo.

Tôi đã thử nghiệm với:

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

Truy vấn được tạo trong đó:

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

và thực hiện kết quả đó trong:

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

1

Cảm giác như đã một năm kể từ khi tôi hỏi điều này, nhưng tôi chỉ vấp phải thứ dường như là thứ chính xác mà tôi đang tìm kiếm! Đó không phải là một câu lệnh SQL, như tôi đã dự đoán, nhưng nó LÀM những gì tôi muốn.

Trong MySQL Workbench, bạn có thể nhấp chuột phải vào bảng hoặc lược đồ và chọn Dữ liệu bảng tìm kiếm.menu ngữ cảnh lược đồ


0

Hãy thử cái này:

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

Điều này giả định rằng không có .trong chuỗi tìm kiếm của bạn. Nếu bạn không thể đảm bảo điều đó, có lẽ bạn có thể sử dụng một ký tự phân tách khác nhau.


1
Bạn có thể giải thích tại sao giải pháp của bạn làm việc xin vui lòng? Mã chỉ trả lời không được xem là một câu trả lời tốt ở đây.
George.Palacios

nó không hoạt động. ví dụ: nếu tìm kiếm te chứa %hoặc _hoặc bất kỳ cột nào chứa.
Jasen

1
@Jasen Bạn có thể thoát các ký tự đặc biệt và sử dụng dấu phân cách khác.
Anon0012398193

@ George.Palacios - bạn thấy gì không rõ ràng?
Anon0012398193

chọn dải phân cách chính xác có thể rất khó khăn. Cách tiếp cận này rất khó để thực hiện đúng
Jasen

0

Giải pháp đơn giản nhất là làm

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

Trừ khi val là một cái gì đó là một sự xuất hiện phổ biến trong cú pháp sql.


Tôi hy vọng bạn đang chế giễu tôi, vì sự thay thế là bạn nghĩ rằng điều này sẽ hữu ích.
donutguy640

1
Tôi chắc chắn là không. Đó là một cách hợp lệ để tìm thứ gì đó nếu bạn không biết "nó" ở đâu trong db / bảng. Grep sẽ trả về toàn bộ các hàng (bao gồm cả tên bảng) nơi có giá trị. Nó không phải là SQL và không hữu ích nếu bạn muốn xử lý đầu ra theo chương trình, nhưng nó đơn giản và khá nhanh.
jkavalik

-2

Thử đi.

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

CONCAT () được sử dụng để phân tách các giá trị cột giống như ở đây, bạn có thể tách cột của mình bằng khoảng trắng để chỉ định kết quả tốt hơn bên trong hàm và kiểm tra giá trị cũng tách chuỗi với không gian và kết quả nằm trong tay bạn.


-3

Có thể bằng cách sử dụng cơ sở dữ liệu information_schema, về cơ bản chúng tôi sẽ chỉ liệt kê tất cả các cột của một bảng cụ thể sau đó sử dụng GROUP_CONCAT để liệt kê chúng dưới dạng một dòng sau đó đưa chúng vào câu lệnh 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');

Điều này sẽ chỉ trả về một hàng nếu 'giá trị' có trong tất cả các cột.


1
Ý bạn là if 'value' is present in any of the columnssao Ngoài ra, bạn có thể thêm một vị từ cho các loại chuỗi như: `và DATA_TYPE IN ('char', 'varchar')`
Lennart

1
Điều này sẽ làm điều đó và hoàn thành mục tiêu của OP là tránh đặt tên rõ ràng cho các cột. Nó không phải là ký tự đại diện, nhưng GROUP_CONCAT chống lại lược đồ thông tin cũng tốt như ký tự đại diện của tất cả các tên cột.
tbrookside

2
Tôi gặp khó khăn khi làm việc này. Tôi đã thay thế db và bảng bằng tên lược đồ và tên bảng của mình, có điều gì khác dự định là giữ chỗ cho tên thực tế không? Ngoài ra, tôi đã tự mình thử tuyên bố bên trong và nhận ra rằng nó CONCAT các tên cột, thay vì dữ liệu của một hàng. Đó có phải là những gì bạn đã dự định?
donutguy640

4
Với tất cả sự tôn trọng, điều này là sai. Truy vấn của bạn sẽ so sánh 'giá trị' với tên của các cột, không phải nội dung của chúng . Tôi phải cung cấp cho một downvote này.
Bill Karwin

4
Chính xác hơn, điều này sẽ so sánh chuỗi 'giá trị' với chuỗi là danh sách tên cột được phân tách bằng dấu phẩy - về cơ bản giống như where 'value' in ('col1,col2,col3…').
Andriy M
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.