如果另一个值不存在,如何根据一个值从表中选择项目? (口才/ SQL) [英] How to select items from a table based on one value if another value does not exists? (eloquent/sql)

查看:204
本文介绍了如果另一个值不存在,如何根据一个值从表中选择项目? (口才/ SQL)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一张桌子,我的网站存储不同的文本块。我正在为每个页面选择正确的块,其中包含页面的块和优选的语言。我想选择相同的文本块(具有相同的标题)在备用语言中,当优先的语言不可用时。



块表

 列:
| id | s lug |标题|语言|内容|

条目:
| 1 |首页|第一| en |第一块|
| 2 |首页|第一| nl | het eerste blok |
| 3 |首页|第二| en |第二块|
- >块第二不适用于'nl'语言

必需的输出

  fallback language = zh 

选择偏好语言= en,输出:
| 1 |首页|第一| en |第一块|
| 3 |首页|第二| en |第二块|

选择首选语言= nl,输出:
| 2 |首页|第一| nl | het eerste blok |
| 3 |首页|第二| en |第二块|
- >选择这个,因为'nl'版本不可用

目前我只是选择了所选择的首选语言,因为如果优先语言块不可用,我不知道如何选择后备语言块。我可以尝试运行两个语言的两个查询,然后合并它们,只要插入后备语言块,如果该块的标题数小于1,但这似乎是非常精致和不是很优雅的



对于我的应用程序,我使用雄辩:

  $ blocks = Block :: - > where('slug','=','home')
- > whereIn('language',$ selectedLanguage)
- > get();

我如何在雄辩中做到这一点? (或在原始SQL中,为此)?

解决方案

如果我正确理解你,如果已经有相同的 slug title



您可以使用LEFT JOIN作为备用语言来检查是否存在具有优先语言的条目。例如,如果你喜欢的语言是nl,后备语言是en,你的查询可能如下所示:

  select blocks * 
从块
左连接块b1
在b1.slug = blocks.slug
和b1.title = blocks.title
和b1.language =' nl'
和blocks.language<> 'nl'
其中blocks.slug ='home'
和blocks.language('nl','en')
和b1.id为空

sqlfiddle



加入的单词可能是一样的:寻找一个更好的翻译相同的 slug 标题。如果该语言是首选的,则不会有匹配,因为 blocks.language<> NL 。否则,联盟将搜索优先翻译('b1.language ='nl')。



在WHERE子句中,我们只会在没有找到更好的翻译( b1.id为null )的情况下返回行。



最好我可以将查询转换为雄辩是:

  $ prefered ='nl'; 
$ fallback ='en';

$ blocks = App \Block :: where('blocks.slug','=','home')
- > whereIn('blocks.language',[$ (
- > leftJoin('blocks as b1',function($ join){
$ join-> on('b1.slug','=','blocks
- > on('b1.title','=','blocks.title')
- > on('b1.language','=',DB: :raw('?'))
- > on('blocks.language','',DB :: raw('?'))
;
} )
- > whereNull('b1.id')
- > addBinding([$ prefended,$ preference],'join')
- > select(DB :: raw ('blocks。*'))
- > get()
;

注意:我假设标题对于所有语言的块是相同的。否则,您将需要另一列(如 block_id )来标识块。


I have a table where I store different blocks of texts for my website. I am currently selecting the correct blocks for each page with the slug of the page, and the prefered language. I would like to select the same block of text (with the same title) in the fallback language when the prefered language is not available.

The blocks table

columns:
| id | slug | title | language | content |

entries:
| 1 | home | first | en | the first block |
| 2 | home | first | nl | het eerste blok |
| 3 | home | second | en | the second block |
    --> block "second" not available for the 'nl' language

Required output

fallback language = en

selected prefered language = en, output:
| 1 | home | first | en | the first block |
| 3 | home | second | en | the second block |

selected prefered language = nl, output:
| 2 | home | first | nl | het eerste blok |
| 3 | home | second | en | the second block |
     --> select this one, because the 'nl' version is not available

Currently I am only selecting the blocks with the selected prefered language, because I don't know how to approach this with selecting the 'fallback language' block if the 'prefered language' block is not available. I could try to run two queries for both languages, and then merge them somehow and only inserting the 'fallback language' blocks if the title count of this block is lower than 1, but this seems quite elaborate and not very elegant?

For my app I am using eloquent:

$blocks = Block::->where('slug', '=', 'home')
                ->whereIn('language', $selectedLanguage)
                ->get();

How could I do this in eloquent? (or in raw SQL, for that matter?)

解决方案

If i understand you correctly, you want to "remove" the rows with the fallback language if there is already a row with the prefered language for the same slug and title.

You can use a LEFT JOIN for the fallback language to check if an entry with the prefered language exists. For example if your preferd language is 'nl' and the fallback language is 'en' your query could look like:

select blocks.*
from blocks
left join blocks b1
    on  b1.slug  = blocks.slug
    and b1.title = blocks.title
    and b1.language = 'nl'
    and blocks.language <> 'nl'
where blocks.slug = 'home'
  and blocks.language in ('nl', 'en')
  and b1.id is null

sqlfiddle

The join in words could be somthing like: Look for a better translation for the same slug and title. If the language is the prefered one there won't be a match because of blocks.language <> 'nl'. Otherwise the join will "search" for the prefered translation ('b1.language = 'nl').

In the WHERE clause we tell only to return rows if no better translation has been found (b1.id is null).

Best i could do to convert the query to eloquent is:

$prefered = 'nl';
$fallback = 'en';

$blocks = App\Block::where('blocks.slug', '=', 'home')
    ->whereIn('blocks.language', [$prefered, $fallback])
    ->leftJoin('blocks as b1', function($join) {
        $join->on('b1.slug', '=', 'blocks.slug')
             ->on('b1.title', '=', 'blocks.title')
             ->on('b1.language', '=', DB::raw('?'))
             ->on('blocks.language', '<>', DB::raw('?'))
        ;
    })
    ->whereNull('b1.id')
    ->addBinding([$prefered, $prefered], 'join')
    ->select(DB::raw('blocks.*'))
    ->get()
;

Note: I'm assuming that title is the same for a block in all languages. Otherwise you would need another column (like block_id) to identify a block.

这篇关于如果另一个值不存在,如何根据一个值从表中选择项目? (口才/ SQL)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆