简体   繁体   English

postgres function:传递并遍历数组

[英]postgres function: pass and iterate through array

I have no clue if what I'm trying to do is possible in PostgreSQL.我不知道我正在尝试做的事情是否可能在 PostgreSQL 中。 But here we go: I want to pass an array of strings to a function.但是在这里我们 go:我想将字符串数组传递给 function。 Then I want to iterate through this array and want to SELECT data from a table based on the current string.然后我想遍历这个数组,并想从基于当前字符串的表中SELECT数据。

The selected data should be pushed to a new array(or table?) which is returned when the iteration is finished.选择的数据应该被推送到一个新的数组(或表?),当迭代完成时返回。

Here is a simplified version of what I'm trying to do in JavaScript:这是我在 JavaScript 中尝试做的简化版本:

const symbols = ["PAM", "EVC", "BIBI", "AA"];

const getLatestQuotes = (tickerSymbols) => {
  const dataToReturn = [];
  tickerSymbols.forEach((symbol) => {
    // do something with symbol
    const newVal = "bla bla" + symbol;

    dataToReturn.push(newVal);
  });

  return dataToReturn;
};

const quotes = getLatestQuotes(symbols);

console.log("quotes", quotes);

EDIT: here is what I have SQL-wise so far:编辑:这是我到目前为止所拥有的 SQL:

CREATE OR REPLACE FUNCTION get_latest_quotes
(
    ArrayText character varying[]
)
RETURNS TABLE (ticker VARCHAR(10), quotetime text, price text) AS
$BODY$
DECLARE
    Counter INT = 0 ;
BEGIN
    CREATE TEMP TABLE ArrayData(ticker VARCHAR(10), quotetime text, price text);
    FOR Counter in array_lower(ArrayText, 1) .. array_upper(ArrayText, 1)
    LOOP
        INSERT INTO ArrayData VALUES(
      SELECT ticker, quotetime, price FROM quotes WHERE ticker = ArrayText[Counter];
    );
    END LOOP;

    RETURN QUERY
    SELECT ArrayTextData
    FROM ArrayData;

    DISCARD TEMP;
END;
$BODY$
LANGUAGE plpgsql VOLATILE;

I hope this kind of explains what I'm trying to do.我希望这种解释我正在尝试做的事情。

EDIT2: Thank you @a_horse_with_no_name, that helps a lot. EDIT2:谢谢@a_horse_with_no_name,这很有帮助。 One more question though.不过还有一个问题。 What I get back looks like this:我回来的样子是这样的:

{ ticker: 'AAPL', timestamp: '934934400', price: 0.54000002145767 },
{ ticker: 'AAPL', timestamp: '935020800', price: 0.51999998092651 },
{ ticker: 'AAPL', timestamp: '935107200', price: 0.52999997138977 },
{ ticker: 'AAPL', timestamp: '935366400', price: 0.54000002145767 },
{ ticker: 'AAPL', timestamp: '935452800', price: 0.54000002145767 },
{ ticker: 'AAPL', timestamp: '935539200', price: 0.55000001192093 },
.
.
.
{ ticker: 'MSFT', timestamp: '934848000', price: 0.54000002145767 },
{ ticker: 'MSFT', timestamp: '934934400', price: 0.54000002145767 },
{ ticker: 'MSFT', timestamp: '935020800', price: 0.51999998092651 },
{ ticker: 'MSFT', timestamp: '935107200', price: 0.52999997138977 },
{ ticker: 'MSFT', timestamp: '935366400', price: 0.54000002145767 },
{ ticker: 'MSFT', timestamp: '935452800', price: 0.54000002145767 },
{ ticker: 'MSFT', timestamp: '935539200', price: 0.55000001192093 },
.
.
.
{ ticker: 'GOOGL', timestamp: '934848000', price: 0.54000002145767 },
{ ticker: 'GOOGL', timestamp: '934934400', price: 0.54000002145767 },
{ ticker: 'GOOGL', timestamp: '935020800', price: 0.51999998092651 },
{ ticker: 'GOOGL', timestamp: '935107200', price: 0.52999997138977 },
{ ticker: 'GOOGL', timestamp: '935366400', price: 0.54000002145767 },
{ ticker: 'GOOGL', timestamp: '935452800', price: 0.54000002145767 },
{ ticker: 'GOOGL', timestamp: '935539200', price: 0.55000001192093 },

Now, I only want the row for each ticker symbol with the newest timestamp.现在,我只想要具有最新时间戳的每个股票代码的行。 How can I do this with SQL?我怎么能用 SQL 做到这一点?

EDIT3:编辑3:

I've managed to figure it out (almost):我已经设法弄清楚(几乎):

CREATE OR REPLACE FUNCTION get_latest_quotes(ArrayText character varying[])
  RETURNS TABLE (ticker VARCHAR(10), "timestamp" int8, price float8) AS
$BODY$
  SELECT ticker, timestamp, price 
  FROM base.quotes 
  WHERE ticker = any(arraytext) 
  ORDER BY timestamp DESC
  LIMIT 10;
$BODY$
LANGUAGE sql
stable;

That does almost what I want.这几乎是我想要的。 This is what it gives me:这就是它给我的:

AAPL    1615901400  123.99
MSFT    1615901400  234.81
RIO.AX  1615852800  114.13
AAPL    1615838402  123.99

As you see, FB is missing, because it has an older timestamp than AAPL.如您所见, FB丢失了,因为它的时间戳比 AAPL 旧。 How can can I tell SQL that I only want one row for each ticker symbol I pass?我怎样才能告诉 SQL 我只想要我通过的每个股票代码的一行?

You don't need a loop, a temp table or even PL/pgSQL for this.为此,您不需要循环、临时表甚至 PL/pgSQL。

This can be achieved with a single query:这可以通过单个查询来实现:

CREATE OR REPLACE FUNCTION get_latest_quotes(ArrayText character varying[])
  RETURNS TABLE (ticker VARCHAR(10), quotetime text, price text) AS
$BODY$
  SELECT ticker, quotetime, price 
  FROM quotes 
  WHERE ticker = any(arraytext);
$BODY$
LANGUAGE sql
stable;

You can use the function like a table:您可以像使用表格一样使用 function:

select *
from get_latest_quotes(array['PAM', 'EVC', 'BIBI', 'AA']);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM