选择-筛选出符合条件的结果

时间:2019-02-03 23:01:11

标签: mysql

我有两个关系表。从他们那里,我想计算出一个SELECT查询,该查询检索列中“介于”值之间的项目。

我是MySQL的新手,这种查询并不是我的强项。我确定我是从错误的角度看问题。希望我能从这里站稳脚跟!

好吧,这行:我有两个表: products line_items ,其中 product_id 是第一个的主键,带有一个与后者中的匹配字段有很多关系。这些表包含以下列:

产品

product_id

line_items

product_id
timestamp_out
timestamp_in

时间戳记指示何时已从库存中取出产品,何时又将其重新插入库存中。相同的 product_id 可以在 line_items 中出现多次,并且 timestamp_out 总是小于 timestamp_in

我想做的是在未“签出”产品时检索 product_id

例如 product_id 1,可能在 line_items 中包含以下行:

第一行

-timestamp_out: 1
-timestamp_in: 3

第二行

-timestamp_out: 6
-timestamp_in: 7

我想要实现的是一个查询,该查询将使用两个任意时间戳,并返回在两个时间戳之间未检出的产品(例如,查询中的时间戳是否为:4和6:那么不应返回product_id 1,因为该范围的上限频谱与第二行的时间跨度交叉;仅当查询中的时间戳超出:4和in:5或更高时7应该返回 product_id 1)。

我尝试了几种查询变体,但我想是“最接近”的一种:

SELECT
    products.product_id
FROM
    products
INNER JOIN
    line_items
ON
    (products.product_id = line_items.product_id)
WHERE
    6 NOT BETWEEN line_items.timestamp_out AND timestamp_in
OR 
    4 NOT BETWEEN line_items.timestamp_out AND timestamp_in

这不起作用,因为它返回 product_id 1,看看第一行的条件如何。如果我将其反转为:

WHERE
    6 BETWEEN line_items.timestamp_out AND timestamp_in
OR 
    4 BETWEEN line_items.timestamp_out AND timestamp_in

...这当然也会返回 product_id 1,因为查询的跨度与第二行的跨度交叉。

希望我能解决问题!我必须承认,在过去的几个小时中,我对此感到有些不安,而又无法全神贯注于如何进行这类MySQL查询!

2 个答案:

答案 0 :(得分:0)

这是一个适合您的用例的查询。

public class AudioProcessor {

    private Context context;
    private FFmpeg ffmpeg;
    private AudioProcessorListener listener;

    private File micPcmFile;
    private File backgroundMp3File;

    private File pcmtowavTempFile;
    private File mp3towavTempFile;
    private File combinedwavTempFile;

    private File outputFile;
    private File volumeChangedTempFile;

    private FFtask currentTask;

    private int videoRecordingLength = 0;

    TextView extensionDownload, percentProgress;

    private static final String TAG = "FFMPEG AV Processor";

    public AudioProcessor(Context context, Activity activity) {
        ffmpeg = null;
        ffmpeg = FFmpeg.getInstance(context);
        percentProgress = activity.findViewById(R.id.percentProgress);
        percentProgress.setSingleLine(false);
        this.context = context;
        prepare();
    }

    /**
     * Program main method. Starts running program
     * @throws Exception
     */
    public void process() throws Exception {
        if (!ffmpeg.isSupported()) {
            Log.e(TAG, "FFMPEG not supported! Cannot convert audio!");
            throw new RuntimeException("FFMPeg has to be supported");
        }
        if (!checkIfAllFilesPresent()) {
            Log.e(TAG, "All files are not set yet. Please set file first");
            throw new RuntimeException("Files are not set!");
        }

        Log.e(TAG, "Start processing audio!");
        listener.onStart();

        Handler handler = new Handler();
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                convertPCMToWav();
            }
        }, 200);
    }

    /**
     * Prepares program
     */
    private void prepare() {
        Log.d(TAG, "Preparing everything...");
        prepareTempFiles();
    }

    /**
     * Converts PCM to wav file. Automatically create new file.
     */
    private void convertPCMToWav() {
        Log.d(TAG, "Convert PCM TO Wav");
        //ffmpeg -f s16le -ar 44.1k -ac 2 -i file.pcm file.wav
        String[] cmd = { "-f" , "s16le", "-ar", "44.1k", "-i", micPcmFile.toString(), "-y", pcmtowavTempFile.toString()};
        currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {

            @Override
            public void onStart() {
                super.onStart();
                percentProgress.setVisibility(View.VISIBLE);
                percentProgress.setText("Converting your recording\n"+"1/5");
            }

            @Override
            public void onSuccess(String message) {
                super.onSuccess(message);
                convertMP3ToWav();
            }
            @Override
            public void onFailure(String message) {
                super.onFailure(message);
                onError(message);
                convertPCMToWav();
            }
        });
    }

    /**
     * Converts mp3 file to wav file.
     * Automatically creates Wav file
     */
    private void convertMP3ToWav() {
        Log.e(TAG, "Convert MP3 TO Wav");

        //ffmpeg -ss 0 -t 30 -i file.mp3 file.wav
        //String[] cmd = { "-ss", "0", "-t", Integer.toString(videoRecordingLength), "-i" , backgroundMp3File.toString(), "-y", mp3towavTempFile.toString() };
        String[] cmd = {  "-i" , backgroundMp3File.toString(), "-y", mp3towavTempFile.toString() };
        currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
            @Override
            public void onStart() {
                super.onStart();
                percentProgress.setText("Converting background audio\n"+"2/5");
                Log.d(TAG, "Convert MP3 TO Wav");
            }
            @Override
            public void onSuccess(String message) {
                super.onSuccess(message);
                changeMicAudio();
            }
            @Override
            public void onFailure(String message) {
                super.onFailure(message);
                Log.e(TAG, "Failed to convert MP3 TO Wav");
                onError(message);
                throw new RuntimeException("Failed to convert MP3 TO Wav");
            }
        });
    }

    /**
     * Combines 2 wav files into one wav file. Overlays audio
     */
    private void combineWavs() {
        Log.e(TAG, "Combine wavs");
        //ffmpeg -i C:\Users\VR1\Desktop\_mp3.wav -i C:\Users\VR1\Desktop\_pcm.wav -filter_complex amix=inputs=2:duration=first:dropout_transition=3 C:\Users\VR1\Desktop\out.wav

        String[] cmd = { "-i" , pcmtowavTempFile.toString(), "-i", volumeChangedTempFile.toString(), "-filter_complex", "amix=inputs=2:duration=first:dropout_transition=3", "-y",combinedwavTempFile.toString()};
        currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
            @Override
            public void onStart() {
                super.onStart();
                percentProgress.setText("Combining the two audio files\n"+"4/5");
            }

            @Override
            public void onSuccess(String message) {
                super.onSuccess(message);
                encodeWavToAAC();

            }
            @Override
            public void onFailure(String message) {
                super.onFailure(message);
                onError(message);
            }
        });
    }

    private void changeMicAudio(){
        Log.e(TAG, "Change audio volume");
        //ffmpeg -i input.wav -filter:a "volume=1.5" output.wav

        String[] cmdy = { "-i", mp3towavTempFile.toString(),  "-af", "volume=0.9", "-y",volumeChangedTempFile.toString()};
        currentTask = ffmpeg.execute(cmdy, new ExecuteBinaryResponseHandler() {

            @Override
            public void onStart() {
                super.onStart();
                percentProgress.setText("Normalizing volume\n"+"3/5");
            }

            @Override
            public void onSuccess(String message) {
                combineWavs();
                super.onSuccess(message);
            }
            @Override
            public void onFailure(String message) {
                super.onFailure(message);
                Log.e("AudioProcessor", message);
            }
        });
    }


    /**
     * Do something on error. Releases program data (deletes files)
     * @param message
     */
    private void onError(String message) {
        completed();
        if (listener != null) {
            //listener.onError(message);
        }
    }
    /**
     * Encode to AAC
     */
    private void encodeWavToAAC() {
        Log.d(TAG, "Encode Wav file to AAC");
        //ffmpeg -i file.wav -c:a aac -b:a 128k -f adts output.m4a
        String[] cmd = { "-i" , combinedwavTempFile.toString(), "-c:a", "aac", "-b:a", "128k", "-f", "adts", "-y",outputFile.toString()};
        currentTask = ffmpeg.execute(cmd, new ExecuteBinaryResponseHandler() {
            @Override
            public void onStart() {
                super.onStart();
                percentProgress.setText("Normalizing volume\n"+"3/5");
            }

            @Override
            public void onSuccess(String message) {
                super.onSuccess(message);
                if (listener != null) {
                    listener.onSuccess(outputFile);
                }
                completed();
            }
            @Override
            public void onFailure(String message) {
                super.onFailure(message);
                onError(message);
                encodeWavToAAC();
            }
        });
    }

    /**
     * Uninitializes class
     */
    private void completed() {
        if (listener != null) {
            listener.onFinish();
        }
        Log.d(TAG, "Process completed successfully!");
        destroyTempFiles();
    }

    /**
     * Prepares temp required files by deleteing them if they exsist.
     * Files cannot exists before ffmpeg actions. FFMpeg automatically creates those files.
     */
    private void prepareTempFiles() {
        Log.d(TAG, "Preparing Temp files...");
        pcmtowavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_pcm.wav");
        mp3towavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_mp3.wav");
        combinedwavTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_combined.wav");
        volumeChangedTempFile = new File(context.getFilesDir()+ Common.TEMP_LOCAL_DIR + "/" + "_volumeChanged.wav");
    }

    /**
     * Destroys temp required files
     */
    private void destroyTempFiles() {
        Log.d(TAG, "Destroying Temp files...");
        pcmtowavTempFile.delete();
        mp3towavTempFile.delete();
        combinedwavTempFile.delete();
        volumeChangedTempFile.delete();
        Log.d(TAG, "Destroying files completed!");
    }


    /**
     * Checks if all files are set, so we can process them
     * @return - all files ready
     */
    private boolean checkIfAllFilesPresent() {
        if(micPcmFile == null || backgroundMp3File == null || outputFile == null) {
            Log.e(TAG, "All files are not set! Set all files!");
            throw new RuntimeException("Output file is not present!");
        }
        Log.d(TAG, "All files are present!");
        return true;
    }

    public void setOutputFile(File outputFile) {
        this.outputFile = outputFile;
    }

    public void setListener(AudioProcessorListener listener) {
        this.listener = listener;
    }

    public void setMicPcmFile(File micPcmFile) {
        this.micPcmFile = micPcmFile;
    }

    public void setBackgroundMp3File(File backgroundMp3File) {
        this.backgroundMp3File = backgroundMp3File;
    }

    public void setVideoRecordingLength(int seconds) {
        this.videoRecordingLength = seconds;
    }

    /**
     * Quits current processing ffmpeg task
     */
    public void killCurrentTask() {
        if (currentTask != null) {
            currentTask.killRunningProcess();
        }
    }

    public interface AudioProcessorListener {
        void onStart();
        void onSuccess(File output);
        void onError(String message);
        void onFinish();
    }
}

对于每种产品,查询确保select p.* from products p where not exists ( select 1 from line_items l where l.product_id = p.product_id AND NOT ( l.timestamp_in < @out OR l.timestamp_out > @in ) ); 中没有记录与给定间隔重叠。

我用您的示例数据 in this db fiddle 进行了测试,它似乎与您的预期结果相符,即:

  • line_items:没有结果
  • @out=4, @in=6:选择了产品1
  • @out=4, @in=5:选择了产品1

答案 1 :(得分:0)

让我们调用定义您要查询query_startquery_end的范围的时间戳。

如果line_items(查询范围在产品缺货前结束)或query_end < timestamp_out行中的时间戳范围与查询范围重叠query_start > timestamp_in(在产品退货后开始查询范围)。

我们正在寻找一种产品,其中该产品的所有line_item行均不与范围重叠-或者,不存在不重叠的行。

select *
from product p
where not exists (
    select *
    from line_items i
    where i.product_id = p.product_id
    and not (@query_end < i.timestamp_out or @query_start > i.timestamp_in)
)