替换雪花中的子查询

时间:2021-05-21 10:57:15

标签: snowflake-cloud-data-platform snowflake-schema

我是 Snowflake SQL 的新手,正在尝试将代码从 Oracle SQL 迁移到 Snowflake SQL。

我在 Oracle 中使用了 Snowflake 不支持的子查询,它给出了以下 err-r

<块引用>

SQL 编译错误:无法评估不受支持的子查询类型。

原始 SQL 查询 -

import 'dart:async';
import 'package:audioplayers/audioplayers.dart';
import 'package:audioplayers/notifications.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

    class PlayerWidget extends StatefulWidget {
      final String url;
      final PlayerMode mode;
    
      const PlayerWidget({
        Key? key,
        required this.url,
        this.mode = PlayerMode.MEDIA_PLAYER,
      }) : super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        return _PlayerWidgetState(url, mode);
      }
    }
    
    class _PlayerWidgetState extends State<PlayerWidget> {
      String url;
      PlayerMode mode;
    
      late AudioPlayer _audioPlayer;
      PlayerState? _audioPlayerState;
      Duration? _duration;
      Duration? _position;
    
      PlayerState _playerState = PlayerState.STOPPED;
      PlayingRoute _playingRouteState = PlayingRoute.SPEAKERS;
      StreamSubscription? _durationSubscription;
      StreamSubscription? _positionSubscription;
      StreamSubscription? _playerCompleteSubscription;
      StreamSubscription? _playerErrorSubscription;
      StreamSubscription? _playerStateSubscription;
      StreamSubscription<PlayerControlCommand>? _playerControlCommandSubscription;
    
      bool get _isPlaying => _playerState == PlayerState.PLAYING;
      bool get _isPaused => _playerState == PlayerState.PAUSED;
      String get _durationText => _duration?.toString().split('.').first ?? '';
      String get _positionText => _position?.toString().split('.').first ?? '';
    
      bool get _isPlayingThroughEarpiece =>
          _playingRouteState == PlayingRoute.EARPIECE;
    
      _PlayerWidgetState(this.url, this.mode);
    
      @override
      void initState() {
        super.initState();
        _initAudioPlayer();
      }
    
      @override
      void dispose() {
        _audioPlayer.dispose();
        _durationSubscription?.cancel();
        _positionSubscription?.cancel();
        _playerCompleteSubscription?.cancel();
        _playerErrorSubscription?.cancel();
        _playerStateSubscription?.cancel();
        _playerControlCommandSubscription?.cancel();
        super.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Column(
          mainAxisSize: MainAxisSize.min,
          children: <Widget>[
            Row(
              mainAxisSize: MainAxisSize.min,
              children: [
                IconButton(
                  key: const Key('play_button'),
                  onPressed: _isPlaying ? null : _play,
                  iconSize: 64.0,
                  icon: const Icon(Icons.play_arrow),
                  color: Colors.cyan,
                ),
                IconButton(
                  key: const Key('pause_button'),
                  onPressed: _isPlaying ? _pause : null,
                  iconSize: 64.0,
                  icon: const Icon(Icons.pause),
                  color: Colors.cyan,
                ),
                IconButton(
                  key: const Key('stop_button'),
                  onPressed: _isPlaying || _isPaused ? _stop : null,
                  iconSize: 64.0,
                  icon: const Icon(Icons.stop),
                  color: Colors.cyan,
                ),
                IconButton(
                  onPressed: _earpieceOrSpeakersToggle,
                  iconSize: 64.0,
                  icon: _isPlayingThroughEarpiece
                      ? const Icon(Icons.volume_up)
                      : const Icon(Icons.hearing),
                  color: Colors.cyan,
                ),
              ],
            ),
            Column(
              mainAxisSize: MainAxisSize.min,
              children: [
                Padding(
                  padding: const EdgeInsets.all(12.0),
                  child: Stack(
                    children: [
                      Slider(
                        onChanged: (v) {
                          final Position = v * _duration!.inMilliseconds;
                          _audioPlayer
                              .seek(Duration(milliseconds: Position.round()));
                        },
                        value: (_position != null &&
                                _duration != null &&
                                _position!.inMilliseconds > 0 &&
                                _position!.inMilliseconds <
                                    _duration!.inMilliseconds)
                            ? _position!.inMilliseconds / _duration!.inMilliseconds
                            : 0.0,
                      ),
                    ],
                  ),
                ),
                Text(
                  _position != null
                      ? '$_positionText / $_durationText'
                      : _duration != null
                          ? _durationText
                          : '',
                  style: const TextStyle(fontSize: 24.0),
                ),
              ],
            ),
            Text('State: $_audioPlayerState'),
          ],
        );
      }
    
      void _initAudioPlayer() {
        _audioPlayer = AudioPlayer(mode: mode);
    
        _durationSubscription = _audioPlayer.onDurationChanged.listen((duration) {
          setState(() => _duration = duration);
    
          if (Theme.of(context).platform == TargetPlatform.iOS) {
            // optional: listen for notification updates in the background
            _audioPlayer.notificationService.startHeadlessService();
    
            // set at least title to see the notification bar on ios.
            _audioPlayer.notificationService.setNotification(
              title: 'App Name',
              artist: 'Artist or blank',
              albumTitle: 'Name or blank',
              imageUrl: 'Image URL or blank',
              forwardSkipInterval: const Duration(seconds: 30), // default is 30s
              backwardSkipInterval: const Duration(seconds: 30), // default is 30s
              duration: duration,
              enableNextTrackButton: true,
              enablePreviousTrackButton: true,
            );
          }
        });
    
        _positionSubscription =
            _audioPlayer.onAudioPositionChanged.listen((p) => setState(() {
                  _position = p;
                }));
    
        _playerCompleteSubscription =
            _audioPlayer.onPlayerCompletion.listen((event) {
          _onComplete();
          setState(() {
            _position = _duration;
          });
        });
    
        _playerErrorSubscription = _audioPlayer.onPlayerError.listen((msg) {
          print('audioPlayer error : $msg');
          setState(() {
            _playerState = PlayerState.STOPPED;
            _duration = const Duration();
            _position = const Duration();
          });
        });
    
        _playerControlCommandSubscription =
            _audioPlayer.notificationService.onPlayerCommand.listen((command) {
          print('command: $command');
        });
    
        _audioPlayer.onPlayerStateChanged.listen((state) {
          if (mounted) {
            setState(() {
              _audioPlayerState = state;
            });
          }
        });
    
        _audioPlayer.onNotificationPlayerStateChanged.listen((state) {
          if (mounted) {
            setState(() => _audioPlayerState = state);
          }
        });
    
        _playingRouteState = PlayingRoute.SPEAKERS;
      }
    
      Future<int> _play() async {
        final playPosition = (_position != null &&
                _duration != null &&
                _position!.inMilliseconds > 0 &&
                _position!.inMilliseconds < _duration!.inMilliseconds)
            ? _position
            : null;
        final result = await _audioPlayer.play(url, position: playPosition);
        if (result == 1) {
          setState(() => _playerState = PlayerState.PLAYING);
        }
    
        // default playback rate is 1.0
        // this should be called after _audioPlayer.play() or _audioPlayer.resume()
        // this can also be called everytime the user wants to change playback rate in the UI
        _audioPlayer.setPlaybackRate();
    
        return result;
      }
    
      Future<int> _pause() async {
        final result = await _audioPlayer.pause();
        if (result == 1) {
          setState(() => _playerState = PlayerState.PAUSED);
        }
        return result;
      }
    
      Future<int> _earpieceOrSpeakersToggle() async {
        final result = await _audioPlayer.earpieceOrSpeakersToggle();
        if (result == 1) {
          setState(() => _playingRouteState = _playingRouteState.toggle());
        }
        return result;
      }
    
      Future<int> _stop() async {
        final result = await _audioPlayer.stop();
        if (result == 1) {
          setState(() {
            _playerState = PlayerState.STOPPED;
            _position = const Duration();
          });
        }
        return result;
      }
    
      void _onComplete() {
        setState(() => _playerState = PlayerState.STOPPED);
      }
    }

我重新构建了查询,它编译并提供了相同数量的记录,任何人都可以查看代码并评论它是否相同或正确,请评论相同。

select p."EMPLOYEE#" as Employee_ID,
 (select o."POSITION_NO" from ah_occupancy o where o."EMPLOYEE_NO" = p."EMPLOYEE#" and o."JOB_NO" = p."JOB#" and p."WORKDATE" between o."PORTION_START" and o."PORTION_END") as Position_ID,
    j."COMPANY_CODE",
    date(p."WORKDATE") as Work_Date,
    p."UNIT" as Calculated_Quantity,
    p."PAYCODE"
from
    "ODS"."HRIS"."PEPAYTRAN" p, job j
where p."EMPLOYEE#" =j."EMPLOYEE#"
    and p."JOB#" = j."JOB#"
    and date( p."WORKDATE") between '2021-02-04' and '2021-02-10'-->='11-FEB-2021'
    and p."ORIGIN" not in ('RC101','FC801','WK8276')
    and p."PAYCODE" not in ('GPPL', 'CLAMS')
    and p."PAYCODE" not like 'JK%'
    and p."TP" >= '01-JAN-2021'
    and nvl(p."BATCH#",' ') not in ('MUHTSL','MUHTS','ICWTS','RDOAC','NU011','1')) ;

1 个答案:

答案 0 :(得分:0)

两个查询是等价的。您可以通过运行以下查询来检查两者是否返回相同的信息:

--original query
select 
   p."EMPLOYEE#" as Employee_ID,
   (select 
      o."POSITION_NO" 
   from 
      ah_occupancy o 
   where 
      o."EMPLOYEE_NO" = p."EMPLOYEE#" 
      and o."JOB_NO" = p."JOB#" 
      and p."WORKDATE" between o."PORTION_START" and o."PORTION_END"
   ) as Position_ID,
   j."COMPANY_CODE",
   date(p."WORKDATE") as Work_Date,
   p."UNIT" as Calculated_Quantity,
   p."PAYCODE"
from
    "ODS"."HRIS"."PEPAYTRAN" p, 
    job j
where 
   p."EMPLOYEE#" =j."EMPLOYEE#"
   and p."JOB#" = j."JOB#"
   and date( p."WORKDATE") between '2021-02-04' and '2021-02-10'-->='11-FEB-2021'
   and p."ORIGIN" not in ('RC101','FC801','WK8276')
   and p."PAYCODE" not in ('GPPL', 'CLAMS')
   and p."PAYCODE" not like 'JK%'
   and p."TP" >= '01-JAN-2021'
   and nvl(p."BATCH#",' ') not in ('MUHTSL','MUHTS','ICWTS','RDOAC','NU011','1')) ;
minus
--new query
select 
   p."EMPLOYEE#" as Employee_ID,
   o.position_no as Position_ID,
   j."COMPANY_CODE",
   date(p."WORKDATE") as Work_Date,
   p."UNIT" as Calculated_Quantity,
   p."PAYCODE"
from
    "ODS"."HRIS"."PEPAYTRAN" p,  
    "ODS"."HRIS"."JOB" j, 
    "ODS"."HRIS"."AH_OCCUPANCY" o
where 
   p."EMPLOYEE#" =j."EMPLOYEE#"
   and p."JOB#" = j."JOB#"
   and date( p."WORKDATE") between '2021-02-04' and '2021-02-10'-->='11-FEB-2021'
   and p."ORIGIN" not in ('RC101','FC801','WK8276')
   and p."PAYCODE" not in ('GPPL', 'CLAMS')
   and p."PAYCODE" not like 'JK%'
   and p."TP" >= '01-JAN-2021'
   and nvl(p."BATCH#",' ') not in ('MUHTSL','MUHTS','ICWTS','RDOAC','NU011','1')
   and o."EMPLOYEE_NO" = p."EMPLOYEE#" 
   and o."JOB_NO" = p."JOB#" 
   and p."WORKDATE" between o."PORTION_START" and o."PORTION_END"

您也可以尝试以下同样等效的查询:

select 
   p."EMPLOYEE#" as Employee_ID,
   o.position_no as Position_ID,
   j."COMPANY_CODE",
   date(p."WORKDATE") as Work_Date,
   p."UNIT" as Calculated_Quantity,
   p."PAYCODE"
from
    "ODS"."HRIS"."PEPAYTRAN" p
    inner join  "ODS"."HRIS"."JOB" j
       on (p."EMPLOYEE#" =j."EMPLOYEE#"
           and p."JOB#" = j."JOB#")
    inner join "ODS"."HRIS"."AH_OCCUPANCY" o
       on (o."EMPLOYEE_NO" = p."EMPLOYEE#" 
           and o."JOB_NO" = p."JOB#" 
           and p."WORKDATE" between o."PORTION_START" and o."PORTION_END"  )
where 
   date( p."WORKDATE") between '2021-02-04' and '2021-02-10'-->='11-FEB-2021'
   and p."ORIGIN" not in ('RC101','FC801','WK8276')
   and p."PAYCODE" not in ('GPPL', 'CLAMS')
   and p."PAYCODE" not like 'JK%'
   and p."TP" >= '01-JAN-2021'
   and nvl(p."BATCH#",' ') not in ('MUHTSL','MUHTS','ICWTS','RDOAC','NU011','1')