0

Ambari 2.4.0.1 を使用した HDP-2.5.0.0

Hive テーブルの ReportSetting は次のとおりです。

id int

serializedreportsetting String

列 'serializedreportsetting' は、ソース SQL Server db の XML データ型ですが、Sqoop インポート中に文字列に変換されます。これは、SQL Server でどのように見えるかです。

<ReportSettings4 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <Trigger>
  <Manual>true</Manual>
  </Trigger>
<StartTime>
    <Year>8</Year>
    <Month>1</Month>
    <Day>1</Day>
    <Hour>0</Hour>
    <Minute>0</Minute>
  </StartTime>
  <ReportPeriod>
    <Month>0</Month>
    <Day>0</Day>
    <Hour>0</Hour>
    <Minute>5</Minute>
  </ReportPeriod>
  <Theft>
    <DigitalInput>true</DigitalInput>
    <Can>false</Can>
  </Theft>
  <SequenceNo>0</SequenceNo>
</ReportSettings4>

ハイブ テーブル:

<ReportSettings4 xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><Trigger><Manual>true</Manual></Trigger><StartTime><Year>8</Year><Month>12</Month><Day>31</Day><Hour>23</Hour><Minute>34</Minute></StartTime><ReportPeriod><Month>0</Month><Day>0</Day><Hour>4</Hour><Minute>0</Minute></ReportPeriod><Theft><DigitalInput>false</DigitalInput><Can>false</Can></Theft><SequenceNo>3</SequenceNo></ReportSettings4>

SQL Server で正常に動作するクエリ:

SELECT
r.VehicleId
,rs.value('(Trigger/Manual)[1]', 'bit') AS RS_Trigger_Manual, ,CAST(CONCAT(CASE WHEN rs.value('(StartTime/Year)[1]', 'int') < 10 THEN CONCAT('200',rs.value('(StartTime/Year)[1]', 'int')) ELSE CONCAT('20',rs.value('(StartTime/Year)[1]', 'int')) END,'-',rs.value('(StartTime/Month)[1]', 'int'),'-',rs.value('(StartTime/Day)[1]', 'int'),' ',rs.value('(StartTime/Hour)[1]', 'int'),':',rs.value('(StartTime/Minute)[1]', 'int'),':','00.000') AS datetime) AS RS_StartTime
,rs.value('(ReportPeriod/Month)[1]', 'int') AS RS_ReportPeriod_Month
,rs.value('(ReportPeriod/Day)[1]', 'int') AS RS_ReportPeriod_Day
,rs.value('(ReportPeriod/Hour)[1]', 'int') AS RS_ReportPeriod_Hour
,rs.value('(ReportPeriod/Minute)[1]', 'int') AS RS_ReportPeriod_Minute
,rs.value('(Theft/DigitalInput)[1]', 'bit') AS RS_Theft_DigitalInput
,rs.value('(Theft/Can)[1]', 'bit') AS RS_Theft_Can,rs.value('(SequenceNo)[1]', 'int') 

AS RS_SequenceNo FROM ReportSetting r
  CROSS APPLY SerializedReportSetting.nodes('/*') AS ReportSettings(rs)

私は次のことを考えたり実行したりできます:

  1. CROSS APPLY を使用するには、横方向のビューを使用する必要があると思います。ここでは serializedreportsetting を配列​​として持っていないため、explode() は機能しません。私が正しい方向に考えているかどうか誰かが検証できますか
  2. 組み込みの xpath udfを使用して serializedreportsetting のデータを列として取得しようとしただけですが、レコードを取得できません。次のような試行はほとんどありません。

    ReportSetting limit 1 から xpath(SerializedReportSetting,'/*') を選択します。

    ReportSetting limit 1 から xpath(SerializedReportSetting,'/ReportSettings4') を選択します。

    ReportSetting limit 1 から xpath(SerializedReportSetting,'/Trigger/Manual') を選択します。

**********更新-1************

上記の課題を処理するために regexp_replace を使用しました。

SELECT id,
  xpath_string(SerializedReportSetting,'/ReportSettings/Trigger/Manual')        AS RS_Trigger_Manual,
  xpath_string(SerializedReportSetting,'/ReportSettings/Trigger/DriveChange')   AS RS_Trigger_DriveChange
FROM
  (SELECT id,
    regexp_replace(SerializedReportSetting, 'ReportSettings+\\d','ReportSettings') AS SerializedReportSetting
  FROM reportsetting
  WHERE id IN (1701548,3185,1700231,1700232)
  ) reportsetting_regex;
4

1 に答える 1

1

xpathでは、明示的に次のように述べています。

このxpath()関数は、常に文字列のハイブ配列を返します。式の結果がテキスト以外の値 (別の xml ノードなど) になる場合、関数は空の配列を返します。

したがって、次のいずれかを使用できます。xpath(SerializedReportSetting,'/ReportSettings4/Trigg‌​er/Manual/text()') from ReportSetting limit 1;

または、さらに良いオプションはxpath_boolean/を使用することxpath_intです:

xpath_boolean - XPath 式が true と評価された場合、または一致するノードが見つかった場合、true を返します。

xpath_boolean(SerializedReportSetting,'/ReportSettings4/Trigg‌​er/Manual') from ReportSetting limit 1;

xpath_short、xpath_int、xpath_long これらの関数は、整数の数値を返します。一致が見つからない場合、または一致が見つかったが値が非数値の場合は値ゼロを返します。数学演算がサポートされています。値が戻り型をオーバーフローする場合、その型の最大値が返されます。

xpath_int(SerializedReportSetting,'/ReportSettings4/ReportPeriod/Month') from ReportSetting limit 1;

于 2016-11-03T10:55:08.250 に答える