AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-69106

delatbabel's questions

Martin Hope
delatbabel
Asked: 2017-07-22 21:16:39 +0800 CST

Buscar todas as linhas de A à esquerda da junção B com base no atributo em A

  • 3

Eu tenho 2 tabelas, productse stores, e uma tabela dinâmica no meio chamada product_store.

Aqui está a parte relevante das estruturas da tabela (do MySQL):

produtos

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`global` tinyint(1) NOT NULL DEFAULT '0',

lojas

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,

product_store

`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`product_id` int(10) unsigned NOT NULL,
`store_id` int(10) unsigned NOT NULL,
`show` tinyint(1) NOT NULL,

A lógica dos sinalizadores globalvs é a seguinte:show

  • Se o globalsinalizador for 1, suponha que este produto esteja em todas as lojas, exceto quando houver uma product_storeentrada com show== 0.
  • Se o globalsinalizador for 0, suponha que este produto esteja apenas em lojas onde há uma product_storeentrada com show== 1.

Em outras palavras, global== 1 significa mostrar este produto em todos os lugares, show== 1 significa mostrar o produto nesta loja, show== 0 significa não mostrar o produto nesta loja e showtem precedência sobre global.

O que eu quero fazer é buscar produtos com base em um store_id conhecido, onde:

  • products.global == 1 E NÃO há entrada product_store para product_id, store_id
  • OU
  • há uma entrada product_store para product_id, store_id E product_store.show == 1

Atualmente eu tenho essa consulta, com um GROUP BYe um aninhado SELECT, mas ele puxa muitos registros do banco de dados que são consolidados pelo GROUP BYe é bastante lento. Estou pensando que deve haver algo mais rápido, sem o select aninhado.

SELECT products.id, products.name, products.global, product_store.show, product_store.store_id
    FROM products
    LEFT JOIN product_store ON products.id=product_store.product_id
    WHERE ((products.global=1 AND
          ((SELECT COUNT(*) FROM product_store WHERE product_store.store_id=226 AND product_store.product_id=products.id) = 0)
         )
        OR (product_store.store_id=226 AND product_store.show=1)
        )
    GROUP BY products.id
    ;

226é o ID da loja neste caso, só preciso executar essa consulta para uma loja por vez para que isso possa ser considerado uma constante.

Observe que, se eu fizer a consulta acima com o GROUP BY, estou recebendo cerca de 14 registros, o que está correto (quando eu mesmo faço a contagem). O sistema tem alguns milhares de produtos e algumas centenas de lojas, de modo que a tabela de junção product_store é bastante grande. Se eu fizer a consulta acima sem o GROUP BY, estou recebendo ~ 1500 registros que parecem ser a lista de todas as combinações de produtos/lojas de produtos que se encaixam na LEFT JOINcláusula.

Apenas para reiterar, a consulta acima funciona bem (embora nas versões do MySQL > 5.7.5 haverá problemas com o GROUP BY), mas parece ser ineficiente e estou tentando descobrir algo melhor e mais rápido.

ALGUNS DETALHES ADICIONAIS SOBRE O CONTEÚDO DA TABELA

Aqui estão algumas consultas rápidas sobre os produtos e lojas relevantes, etc. Primeiro para mostrar TODOS os produtos correspondentes relevantes -- há 15, todos com global=1.

SELECT products.id, MD5(products.name), products.global
    FROM products
    -- .. omitted some classification information here
    ;

+-----+----------------------------------+--------+
| id  | md5(products.name)               | global |
+-----+----------------------------------+--------+
| 555 | 56e597c43cff47af57f006b7de7ff552 |      1 |
| 591 | 7ba5549546ce20e1dee02c7f6454b16f |      1 |
| 558 | 7b66d8dce0c112b3966d1940de44f9ad |      1 |
| 556 | bd3d39b9f5194184ea0853c70d7faa07 |      1 |
| 590 | ef6eccbd3795fbe70890220c09ed880d |      1 |
| 559 | b763e2b9ba305538b497da97fba066ca |      1 |
| 593 | e26744d617ed12ebffea4b996fecbbef |      1 |
| 594 | 06ba8ab6649c83577db053e4a89c1655 |      1 |
| 596 | 79f9241643e84e2a27bfc0b260432e82 |      1 |
| 595 | 85fe772dc61d27292c09a7604cf76dd7 |      1 |
| 597 | fd6c21db00e1b679c0d0d2ef8f3f6e00 |      1 |
| 560 | c8056818e3ed5885188d78a9440fa77c |      1 |
| 561 | 33d79c194e39e8e84cf743eefcd909df |      1 |
| 562 | 1c74d85823e509ab4b09e82314b09604 |      1 |
| 557 | b6a8027035b63bd4d4bd21169434426d |      1 |
+-----+----------------------------------+--------+

Agora, observe a junção com a tabela product_store. Há apenas uma entrada para store_id 226 e tem show=0.

SELECT products.id, MD5(products.name), products.global, product_store.show
    FROM products
    INNER JOIN product_store ON products.id=product_store.product_id
    -- omitted the classification information as per the above
    WHERE product_store.store_id=226
    ;

+-----+----------------------------------+--------+------+
| id  | MD5(products.name)               | global | show |
+-----+----------------------------------+--------+------+
| 555 | 56e597c43cff47af57f006b7de7ff552 |      1 |    0 |
+-----+----------------------------------+--------+------+

... Portanto, preciso ser capaz de construir uma consulta que selecione todos os 15 produtos onde global=1 EXCETO o produto onde product_store.show=0, portanto, preciso do conjunto de 14 produtos restantes.

Uma seleção UNION funcionaria de alguma forma? Ou alguma forma de interseção?

Exemplo: http://sqlfiddle.com/#!9/1342cf/5

mysql performance
  • 1 respostas
  • 1954 Views
Martin Hope
delatbabel
Asked: 2015-12-27 05:09:11 +0800 CST

Tabela chave/valor com limitadores

  • 2

Tenho certeza que alguém deve ter encontrado isso ou um problema como esse antes, mas não estou encontrando nada em uma pesquisa no Google ou DBA Exchange.

Eu tenho uma tabela armazenando pares chave/valor. Existem também 2 colunas limitantes na tabela, host e ambiente, ambas anuláveis. A maneira como as tabelas de limitação funcionam é que, se houver uma entrada na coluna do host, a chave/valor se aplicará a esse host; da mesma forma, se houver uma entrada na coluna do ambiente, essa entrada terá efeito apenas para esse ambiente. Se uma chave/valor for procurado com um host ou ambiente, os valores limitados prevalecem sobre os valores em que host=NULL ou ambiente=NULL. Além disso, o host tem precedência sobre o ambiente.

Então, como exemplo, aqui estão algumas entradas da tabela:

id      env     host     key    value
1       NULL    NULL     fruit  apple
2       prod    NULL     fruit  banana
3       prod    www      fruit  mango
4       test    NULL     fruit  peach
5       NULL    test     fruit  orange

Dados esses dados de exemplo, o que estou procurando é uma instrução (ou instruções) SQL que retornará esses dados com base nestes critérios:

env     host   key    data returned
NULL    NULL   fruit  1, fruit, apple
prod    NULL   fruit  2, fruit, banana
NULL    www    fruit  3, fruit, mango
junk    junk   fruit  1, fruit, apple  // NULL/NULL values are used as a fallback
junk    www    fruit  1, fruit, apple  // no match, fallback
prod    test   fruit  5, fruit, orange // host=test takes precedence

Isso faz sentido?

Posso dividir a pesquisa em várias seleções, tentar cada uma, verificar se consigo um resultado etc., mas espero conseguir isso da maneira mais eficiente possível.

Idealmente, gostaria que o tipo de pesquisa fosse facilmente extensível se mais limitadores fossem adicionados posteriormente (por exemplo, grupo, namespace, etc).

Alguém?

performance query-performance
  • 1 respostas
  • 77 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host

    • 12 respostas
  • Marko Smith

    Como fazer a saída do sqlplus aparecer em uma linha?

    • 3 respostas
  • Marko Smith

    Selecione qual tem data máxima ou data mais recente

    • 3 respostas
  • Marko Smith

    Como faço para listar todos os esquemas no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Listar todas as colunas de uma tabela especificada

    • 5 respostas
  • Marko Smith

    Como usar o sqlplus para se conectar a um banco de dados Oracle localizado em outro host sem modificar meu próprio tnsnames.ora

    • 4 respostas
  • Marko Smith

    Como você mysqldump tabela (s) específica (s)?

    • 4 respostas
  • Marko Smith

    Listar os privilégios do banco de dados usando o psql

    • 10 respostas
  • Marko Smith

    Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL?

    • 4 respostas
  • Marko Smith

    Como faço para listar todos os bancos de dados e tabelas usando o psql?

    • 7 respostas
  • Martin Hope
    Jin conectar ao servidor PostgreSQL: FATAL: nenhuma entrada pg_hba.conf para o host 2014-12-02 02:54:58 +0800 CST
  • Martin Hope
    Stéphane Como faço para listar todos os esquemas no PostgreSQL? 2013-04-16 11:19:16 +0800 CST
  • Martin Hope
    Mike Walsh Por que o log de transações continua crescendo ou fica sem espaço? 2012-12-05 18:11:22 +0800 CST
  • Martin Hope
    Stephane Rolland Listar todas as colunas de uma tabela especificada 2012-08-14 04:44:44 +0800 CST
  • Martin Hope
    haxney O MySQL pode realizar consultas razoavelmente em bilhões de linhas? 2012-07-03 11:36:13 +0800 CST
  • Martin Hope
    qazwsx Como posso monitorar o andamento de uma importação de um arquivo .sql grande? 2012-05-03 08:54:41 +0800 CST
  • Martin Hope
    markdorison Como você mysqldump tabela (s) específica (s)? 2011-12-17 12:39:37 +0800 CST
  • Martin Hope
    Jonas Como posso cronometrar consultas SQL usando psql? 2011-06-04 02:22:54 +0800 CST
  • Martin Hope
    Jonas Como inserir valores em uma tabela de uma consulta de seleção no PostgreSQL? 2011-05-28 00:33:05 +0800 CST
  • Martin Hope
    Jonas Como faço para listar todos os bancos de dados e tabelas usando o psql? 2011-02-18 00:45:49 +0800 CST

Hot tag

sql-server mysql postgresql sql-server-2014 sql-server-2016 oracle sql-server-2008 database-design query-performance sql-server-2017

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve