Как я комбинирую 2 избранных оператора в один?

1110 Это звучит как безумие, но я полагаю, у вас есть на то веские причины. Жизнь без веселья без небольшого количества безумия.

Один из подходов, который вы можете использовать, - это использовать ассемблер во время сборки для генерации констант во время компиляции.

Первый шаг - создать файл, содержащий все инструкции по сборке, которые вы будете использовать, по одной на строку.

Например:

cmpwi   3,0x20
addi    3,3,0
blr

Назовите этот файл input.def. Затем используйте этот скрипт:

#!/usr/bin/env bash

(cat << HEADER
    .global main
    .text
main:
HEADER
cat input.def) > asm.s

powerpc-linux-gnu-as asm.s -o asm.o

powerpc-linux-gnu-objdump -d asm.o | \
    sed '1,/<main>/ d' | \
    paste -d'\t' - input.def | \
    awk -F'\t' '{
        bytes=$2
        asm=$4
        disasm=$3
        gsub(/ /, "", bytes);
        gsub(/[, ]+/, "_", asm);
        printf("#define ASM_%-20s 0x%s    // disassembly: %s\n", asm, bytes, disasm)
    }'

# Clean temporaries
rm asm.s asm.o

(здесь я использую GNU-ассемблер и objdump. Возможно, вам придется изменить эту часть, если вы не используете эти инструменты. Objdump используется в качестве прославленного hexdump утилита здесь.)

Этот скрипт оболочки:

  1. Создает файл сборки
  2. Собирает его
  3. Помещает его рядом с input.def , (Это позволяет увидеть, какую сборку вы набрали.)
  4. Переформатирует гекс так, чтобы он был допустимой константой Си. Переформатирует asm, чтобы он был допустимым символом C. Затем пишет определение для сопоставления имени инструкции с константой.
  5. Поместите все это в asm.h

Это большая работа, но вы можете сделать все это во время компиляции.

Это создает заголовочный файл с именем asm.h:

#define ASM_cmpwi_3_0x20         0x2c030020    // disassembly: cmpwi   r3,32
#define ASM_addi_3_3_0           0x38630000    // disassembly: addi    r3,r3,0
#define ASM_blr                  0x4e800020    // disassembly: blr

Вы используете файл asm.h так:

#include "asm.h"
*((volatile int *)(0x80001234)) = ASM_cmpwi_3_0x20;

Если вам нужна новая константа asm, отредактируйте input.def и перезапустите сценарий оболочки.

45
задан Mat 4 May 2013 в 10:44
поделиться

7 ответов

У Вас есть два варианта здесь. Первое должно иметь два набора результатов, которые установят 'Test1' или 'Test2' на основе условия в WHERE пункт, и затем UNION их вместе:

select 
    'Test1', * 
from 
    TABLE 
Where 
    CCC='D' AND DDD='X' AND exists(select ...)
UNION
select 
    'Test2', * 
from 
    TABLE
Where
    CCC<>'D' AND DDD='X' AND exists(select ...)

Это могло бы быть проблемой, потому что Вы собираетесь эффективно сканировать/искать на ТАБЛИЦЕ дважды.

другое решение состояло бы в том, чтобы выбрать из таблицы однажды и установить 'Test1' или 'Test2' на основе условий в ТАБЛИЦЕ:

select 
    case 
        when CCC='D' AND DDD='X' AND exists(select ...) then 'Test1'
        when CCC<>'D' AND DDD='X' AND exists(select ...) then 'Test2'
    end,
    * 
from 
    TABLE 
Where 
    (CCC='D' AND DDD='X' AND exists(select ...)) or
    (CCC<>'D' AND DDD='X' AND exists(select ...))

выгода, здесь являющаяся этим, необходимо будет копировать условия фильтра в CASE оператор и WHERE оператор.

61
ответ дан casperOne 26 November 2019 в 21:17
поделиться

Если они от той же таблицы, я думаю UNION , команда, которую Вы ищете.

(Если необходимо было бы когда-либо выбирать значения из столбцов различных таблиц, необходимо посмотреть JOIN вместо этого...)

9
ответ дан Tomas Aschan 26 November 2019 в 21:17
поделиться

Спасибо за вход. Попробованный материал, который был упомянут здесь и это 2, которые я взялся за работу:

(
select 'OK', * from WorkItems t1
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND (BoolField05=1)
)
UNION
(
select 'DEL', * from WorkItems t1
where exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)
)

И

select 
    case
        when
            (BoolField05=1)
    then 'OK'
    else 'DEL'
        end,
        *
from WorkItems t1
Where
            exists(select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
            AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
            AND TimeStamp>'2009-02-12 18:00:00'

, Который был бы самым эффективным из них (редактирование: второе, поскольку это только сканирует таблицу однажды), и действительно ли возможно сделать это еще более эффективным ? (BoolField=1), действительно переменная (dyn sql), который может содержать любого где оператор на таблице.

я работаю на MS SQL 2005. Попробованные примеры Quassnoi, но не работали как ожидалось.

4
ответ дан Wolf5 26 November 2019 в 21:17
поделиться
select Status, * from WorkItems t1
where  exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'

UNION

select 'DELETED', * from WorkItems t1
where  exists (select 1 from workitems t2 where t1.TextField01=t2.TextField01 AND (BoolField05=1) )
AND TimeStamp=(select max(t2.TimeStamp) from workitems t2 where t2.TextField01=t1.TextField01) 
AND TimeStamp>'2009-02-12 18:00:00'
AND NOT (BoolField05=1)

, Возможно, это добилось бы цели. Я не могу протестировать его отсюда, хотя, и я не уверен, против какой версии SQL Вы работаете.

1
ответ дан Kezzer 26 November 2019 в 21:17
поделиться

команда Union - то, в чем Вы нуждаетесь. , Если это не работает, Вы, возможно, должны совершенствовать, в какой среде Вы находитесь.

1
ответ дан JB King 26 November 2019 в 21:17
поделиться

используйте случай в выбор и используйте в, где близкий a ИЛИ

что-то вроде этого, я не сделал протестировал его, но он должен работать, я думаю...

select case when CCC='D' then 'test1' else 'test2' end, *
from table
where (CCC='D' AND DDD='X') or (CCC<>'D' AND DDD='X')
1
ответ дан Fredou 26 November 2019 в 21:17
поделиться

Я думаю, что это - то, что Вы ищете:

SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*
FROM WorkItems t1
WHERE (TextField01, TimeStamp) IN(
  SELECT TextField01, MAX(TimeStamp)
  FROM WorkItems t2
  GROUP BY t2.TextField01
  )
AND TimeStamp > '2009-02-12 18:00:00'

, Если Вы находитесь в Oracle или в MS SQL 2005 и выше, затем Вы могли бы сделать:

SELECT *
FROM (
  SELECT CASE WHEN BoolField05 = 1 THEN Status ELSE 'DELETED' END AS MyStatus, t1.*,
     ROW_NUMBER() OVER (PARTITION BY TextField01 ORDER BY TimeStamp DESC) AS rn
  FROM WorkItems t1
) to
WHERE rn = 1

, это более эффективно.

1
ответ дан Quassnoi 26 November 2019 в 21:17
поделиться
Другие вопросы по тегам:

Похожие вопросы: