我有一个由INT(CUSTOMER)类型的多个记录组成的表,需要为帐户的NAME获取最后两个不同的事务。因此,在我的SQL中,我有以下内容提供了最新的4个交易,这些交易都是正确的(我必须选择最新的4条记录,因为,因为您看到选择最新的两条记录会导致两条记录都是NAME' JOHNSON&#39):
SQL> SELECT ID, NAME, DATE, CUSTOMER
FROM (select * from ORDER_TABLE ORDER BY DATE DESC) ORDER_TABLE
WHERE rownum <= 4
and (CUSTOMER = 1002)
ORDER BY rownum DESC;
ID NAME DATE CUSTOMER
---------- ------------------- --------- ----------
90 SMITH 26-DEC-17 1002
135 JOHNSON 09-DEC-17 1002
235 JOHNSON 01-JAN-18 1002
322 JOHNSON 04-JAN-18 1002
但是,我需要返回的只是最新的DISTINCT NAME命令,所以不过上面的输出,我只想看到:
90 SMITH 26-DEC-17 1002
322 JOHNSON 04-JAN-18 1002
我是否可以在单个语句中执行查询以获取所需的输出?任何帮助将不胜感激!!!!
答案 0 :(得分:0)
这是一种方法 - 使用分析函数。这有点复杂;遗憾的是,count(distinct ...)
可以用作分析函数,但只能使用partition by
子句 - 而不是order by
子句。因此,我们必须使用组启动技术手动创建它。
请注意,WITH子句中的第一个子查询仅用于生成测试数据;如果对实际表使用它,请从代码中删除它,并确保第二个子查询中的表名(和列名!)是正确的。我将列名date
替换为dt
; date
是保留字,不应用作列名。
我正在展示一般解决方案 - 如果需要,您当然可以过滤单个客户编号。 (或者,如果您一次只需要一个客户,则可以稍微简化查询。)
with
tbl ( id, name, dt, customer ) as (
select 90, 'SMITH' , to_date('26-DEC-17', 'dd-MON-rr'), 1002 from dual union all
select 135, 'JOHNSON', to_date('09-DEC-17', 'dd-MON-rr'), 1002 from dual union all
select 235, 'JOHNSON', to_date('01-JAN-18', 'dd-MON-rr'), 1002 from dual union all
select 322, 'JOHNSON', to_date('04-JAN-18', 'dd-MON-rr'), 1002 from dual
),
flg ( id, name, dt, customer, flag ) as (
select id, name, dt, customer,
case when lag(name) over (partition by customer order by dt desc) = name
then null else 1 end
from tbl
),
prep ( id, name, dt, customer, sm ) as (
select id, name, dt, customer,
sum(flag) over (partition by customer order by dt desc)
from flg
)
select max(id) keep (dense_rank first order by dt desc) as id,
name, max(dt) as dt, customer
from prep
where sm <= 2
group by customer, name
;
ID NAME DT CUSTOMER
---------- ------- --------- ----------
90 SMITH 26-DEC-17 1002
322 JOHNSON 04-JAN-18 1002
答案 1 :(得分:0)
在Oracle 12.1及更高版本中,match_recognize
能够快速完成这些要求(并且通常比分析函数方法快得多)。
我不会在本答案中写一篇关于match_recognize
的完整教程;我只想指出{- ... -}
语法中的PATTERN
表示这些行是匹配定义的一部分,但这些行是从输出中排除的。其余部分是match_recognize
的基本应用。
我正在展示一般解决方案 - 如果需要,您当然可以过滤单个客户编号。 (或者,如果您一次只需要一个客户,则可以稍微简化查询。)
with
tbl ( id, name, dt, customer ) as (
select 90, 'SMITH' , to_date('26-DEC-17', 'dd-MON-rr'), 1002 from dual union all
select 135, 'JOHNSON', to_date('09-DEC-17', 'dd-MON-rr'), 1002 from dual union all
select 235, 'JOHNSON', to_date('01-JAN-18', 'dd-MON-rr'), 1002 from dual union all
select 322, 'JOHNSON', to_date('04-JAN-18', 'dd-MON-rr'), 1002 from dual
)
select *
from tbl
match_recognize(
partition by customer
order by dt desc
all rows per match
pattern ( ^ a {- b* -} c )
define b as name = a.name
);
CUSTOMER DT ID NAME
---------- --------- ---------- -------
1002 04-JAN-18 322 JOHNSON
1002 26-DEC-17 90 SMITH
答案 2 :(得分:0)
class UdpServer
{
PrintWriter out;
ButtonHandler txButtonHandler;
BufferedReader in;
DatagramSocket socket;
InetAddress ip = null;
int port;
UdpServer (String gport) throws IOException
{
int i = 0;
socket = new DatagramSocket (Integer.parseInt (gport));
txButtonHandler = new ButtonHandler ();
sendButton.addActionListener (txButtonHandler);
new Thread ()
{
public void run ()
{
try
{
rx ();
}
catch (IOException e)
{
}
}
}.start ();
tx ();
System.exit (1);
}
void tx () throws IOException
{
byte[] buf = new byte[256];
BufferedReader in = new BufferedReader (new InputStreamReader(System.in));
String toServer;
do
{
toServer = in.readLine();
toServer = toServer + "\n";
buf = toServer.getBytes ();
DatagramPacket packet = new DatagramPacket (buf, toServer.length(), ip, port);
if (ip != null) socket.send(packet);
}
while (toServer != null);
socket.close ();
System.exit (1);
}
private class ButtonHandler implements ActionListener
{
public void actionPerformed (ActionEvent event) //throws IOException
{
try{tx ();} catch (IOException e){}
}
}
void rx () throws IOException
{
byte[] buf = new byte[256];
String fromServer;
do
{
for (int i = 0; i < 256; i ++) buf[i] = 0;
DatagramPacket packet = new DatagramPacket (buf, buf.length);
socket.receive (packet);
fromServer = new String (packet.getData());
ip = packet.getAddress ();
port = packet.getPort ();
//System.out.println (port + ":" + ip);
if (fromServer != null) System.out.print (fromServer);
}
while (fromServer != null);
socket.close ();
System.exit (1);
}
}
答案 3 :(得分:-1)
SELECT id, name, date, customer
FROM order_table
WHERE (name, date) IN
(SELECT name, max(date)
FROM order_table
WHERE customer = 1002
GROUP BY name)
;
当然,使用IN并不是大表中最好的,你可以使用内连接。