カテゴリ:PC( 17 )

MySQLでグループごとのランキング(最大値からN件取得)

create table xxx
(
nen int,
gaku int
);

insert into xxx values ( 2011,600 );;
insert into xxx values ( 2011,500 );
insert into xxx values ( 2011,450 );
insert into xxx values ( 2011,750 );
insert into xxx values ( 2010,450 );
insert into xxx values ( 2010,540 );
insert into xxx values ( 2010,350 );
insert into xxx values ( 2010,800 );
insert into xxx values ( 2010,700 );

select t.nen, t.gaku
from ( select
@rnk:=if(@prevnen <=> x.nen, if( @prevaku <=> x.gaku, @rnk, @rnk+1), 1 ) as rnk,
@prevnen := x.nen nen,
@prevgaku := x.gaku gaku
from ( select * from xxx order by nen, gaku desc ) as x
cross join ( select @prevnen:=0, @prevgaku:=0, @rnk:=0 ) as dummy ) t
where t.rnk <= 3;

これが結構速い。
ユーザー変数はMySQLの独自機能だし、項目値にnullがある場合はもう一捻りしなければいけないが。
注意点はユーザ変数への代入順序。
今回の場合は@rnkを最初に持ってこないと@prevnen、@pervgakuが上書きされてしまう。
[PR]
by nora1962 | 2011-03-21 11:32 | PC

CDOにバグ?

http://www.asahi-net.or.jp/~ef2o-inue/vba_o/sub05_800_080.html
にあるようにwindows2000以降のwindowsには「CDO」という機能があります。
(環境がないので、VISTA,office2007で検証していません)

ところがwindows2000、office2000の環境でこの機能使うと起動元のプログラム(EXCEL、ACCESS)
のプロセスが残ってしまった。
いろいろためしたが、残念ながら解決しない。

「basp21」使えばこんな苦労しなくてもいいんだけど。
[PR]
by nora1962 | 2009-11-10 03:47 | PC

thunderbirdで出力したLDIFファイルをwindowsメールでインポート

Thunderbirdで出力したLDIFファイルはそのままではVISTAのwindowsメールではインポートできません。
windowsメールがBASE64でエンコードされたUTF-8コードを読み込めない。
「dn::」レコードを「dn:」にしてSHIFT-JISに展開すればインポートできるようだ。
以下は変換用のRubyスクリプト。あんまりスマートじゃないけど。

require 'nkf'
require 'base64'
$KCONV="SJIS"

while line = ARGF.gets
line = line.chomp
if /([^:]+:): (.*)/ =~ line
$a = $1
$b = $2
buf = NKF.nkf("-Ws", Base64.decode64($b) )
buf = buf.gsub( '"', "" )
buf = $a + " " + buf
else
line = line.gsub( '"', "" )
buf = line
/([^:]+:)/ =~ buf
$a = $1
if $a == "dn:"
if /cn=/ !~ buf
/mail=(.*)/ =~ buf
buf = "dn: cn=" + $1 + ",mail=" + $1
cn = $1
$flg = 1
end
else
if /mail:/ =~ line and $flg == 1
print "cn: " + cn,"\n"
$flg = 0
end
buf = line
end
end
print buf,"\n"
end

[PR]
by nora1962 | 2009-09-24 05:53 | PC

Oracle Database Gateway for ODBC その2

Oracle Database Gateway for ODBC を少しいじってみた。
postgresqlのエントリを追加。

データ型のマッピング

SQLSERVER,Postgresqlとも
create table kkk
(
id int,
name varchar(20),
salary decimal(10,2)
)
で作成。これをORACLE側から見ると
DESC "dbo"."kkk"@mssql

id NUMBER(10)
name VARCHAR2(20)
salary NUMBER(10,2)

DESC "kkk"@postgresql

id NUMBER(10)
name VARCHAR(255)
salary NUMBER(10,2)

postgresqlの文字列型の表示がちょっとおかしい。これはpostgresqlのvarchar型がUTF-8対応
になっており文字数を表しているのにoracleはバイト数基準であるかららしい。
ちなみにpostgresqlで255桁指定まではORACLE側では255表示、それ以上はデータ型がLONG型表示になる。LONG型はoracleでは本来1テーブルに1フィールドしか指定できないが、この場合はoracle側で処理に制限を受けることはなさそう。あくまで見た目ということらしい。

データ操作(INSERT、DELETE、UPDATE)にはoracleの既定の動作と同様にトランザクションが有効になっている。

DELETE FROM "kkk"@postgresql;

と実行してもROLLBACKすればもとに復帰できる。
ただし、SELECT ... FOR UPDATE構文には対応していない。
また、INSERT INTO "kkk"@postgresql SELECT ... でORACLE側のテーブルのデータを一気に流し込むことはできないようだ。
逆にORACLE側に持ってくることはできる。

レスポンスもそんなに悪くはない。思ったよりも使える機能かもしれない。
[PR]
by nora1962 | 2009-09-17 01:00 | PC

SQL CLRでSTRCONV関数

以下の内容のSqlClrStrConv.vbをc:\tmpに作成します。
Imports System
Imports System.Data
Imports System.Data.SqlClient
Imports System.Data.SqlTypes
Imports Microsoft.SqlServer.Server

Public Class SQLCLR
_
Public Shared Function SqlStrConv(ByVal str As SqlString, ByVal mode As SqlInt32) As SqlString
Return StrConv(str.ToString, mode)
End Function
End Class

コンパイルします。
c:\tmp>vbc /out:SqlClrStrConv.dll /t:library /r:"C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn\sqlaccess.dll" SqlClrStrConv.vb

sqlcmdかクエリアナライザで以下のコマンドを実行します。

USE [pubs]
GO
create ASSEMBLY [SqlClrStrConv]
FROM 'C:\tmp\SqlClrStrConv.dll'
WITH PERMISSION_SET = SAFE
GO

create function SqlStrConv( @str nvarchar(max),@conversion int ) returns nvarchar(max)
as external name SqlClrStrConv.SQLCLR.SqlStrConv
go

これで
select cast( dbo.SqlStrConv('abc',4) as nvarchar(10) )
go

で全角に変換できます。
[PR]
by nora1962 | 2009-09-15 22:42 | PC

Vista SP2でACCESS2003が不安定になる

WindowsUpdateで使っているVistaがSP2になった。
そしたら、ACCESS2003の挙動が変になった。データベースウインドウを閉じようとすると「ACCESSの動作
が停止しました」というメッセージが出てACCESSが落ちる。
イベントビューワーを見てみるとNTDLL.DLLで落ちてるっぽい。

環境としてOFFICE2003とOFFICE20007を共存させているのが悪いのかなと思いながら、ググって見た。
その結果、これにちかいかなと見つけたのが
http://support.microsoft.com/kb/945674/ja

この修正をあてたところ、ひとまず解決。
しかし、マイクロソフトにも困ったもんだ。
[PR]
by nora1962 | 2009-09-14 02:47 | PC

Oracle Database Gateway for ODBC

Oracle Database Gateway for ODBCをoracle11gに設定してSqlserver2005と接続してみる。
設定するPCはVista Ultimate
あらかじめODBCのシステムDSN「mssql」を定義しておく。sqlserverの接続データベースはpubs。

(1)initXXX.oraファイルの編集
C:\app\nakagawa_takashi\product\11.1.0\db_1\hs\adminにinitmssql.oraを作成。中身は

HS_FDS_CONNECT_INFO = mssql

(2)listener.oraに以下のように編集

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = nora01)(PORT = 1521))
(ADDRESS = (PROTOCOL = TCP)(HOST = nora01)(PORT = 1522))

)
)
SID_LIST_LISTENER=
(SID_LIST=
(sid_desc=
(sid_name=mssql)
(ORACLE_HOME=C:\app\nakagawa_takashi\product\11.1.0\db_1)
(program=dg4odbc)
)
)

(3)tnsnames.oraに以下の内容を追加
mssql=
(description=
(address=(protocol=tcp)(host=nora01)(port=1522))
(connect_data=(sid=mssql))
(hs=ok)
)

ここでオラクル、オラクルリスナーを再起動。

sqlplusを立ち上げる。
(4)データベースリンク作成。接続ユーザーとパスワードは適宜。

create database link mssql connect to xxx idnetified by xxx using 'mssql';

(5)select文発行

select * from authors@mssql;

行1でエラーが発生しました。:
ORA-28500:
OracleからOracle以外のシステムへの接続で次のメッセージが戻されました:
[Microsoft][SQL Native
Client]他のコマンドの結果のために、接続がビジー状態になっています。
ORA-02063: 先行のエラー・メッセージを参照してください2 lines(MSSQL)。

いろいろ調べたり、試したりしたところスキーマを指定する必要があるみたい。

select * from dbo.authors@mssql;

ところが、

select au_id from dbo.authors@mssql;

だと

行1でエラーが発生しました。:
RA-00904: "AU_ID": 無効な識別子です

どうもカラム名はケースセンシティブなようだ。

select "au_id" from dbo.authors@mssql;

これで通った。

まずはここまで。
[PR]
by nora1962 | 2009-09-11 00:57 | PC

ruby dbi とRDBMS

rubyとdbiで勉強して(あそんで)いる、このごろ。

require 'dbi'
dbh = DBI.connect("dbi:pg:test:localhost","user","password")
row = dbh.select_one( "select * from hoge" )
row.each{|col|
puts col.class
}
でDB側とrubyとでデータ型の関連を調べてみた。
postgvresqlは
int → fixnum
decimal → bigdecmal
varchar → string
float → float
double → float
rubyのfloatはdoubleと同精度。
postgresqlのdecimalがbigdecimalに紐付けられているのは好感がもてる。

mysqlも同様な結果。

ところがoracleは
number(10,2)をFLOATで返してくる。これはまずいんじゃないかな。
ODBC経由にするとnumber型がすべてBigdecimal型で返ってくる。
ORACLEのFLOAT、REALはいずれもstring型。

mssqlもODBC経由なら
int → Fixnum
decimal → bigdecimal
float,real → float

やっぱりORACLEが一番くせが強いかな?
[PR]
by nora1962 | 2009-04-14 05:56 | PC

rubyのsplitではまる

仕事でEXCELから出力したタブ区切りのファイルをWEBシステムにアップロードするというやつをやった。
ところが、出力ファイルの行末のタブの数が行によって違っていて、エラーになって取り込めない。
ruby使って以下のようにやってみた。
io = open(ARGV[0])
line=nil
while line=io.gets
  line.chomp!
  s = line.split(/\t/)
  print line
  print( "\t" * ( ARGV[1] - s.length ) )
  puts
end
ところがこれじゃうまく動かない。タブの数が余計に出力される。
なぜだかわからず、結構悩んでしまった。

これはsplitの仕様のせい。
"A\tB".split → [ "A", "B" ]
"A\t\tB".split → [ "A","", "B" ]
だが
"A\t\t".split → [ "A" ]
となってしまうのが原因。空文字と区切り文字が後続する部分は切り捨てられてしまう。

念のためPerl5.8で試したみたところ同様の動作を行ってた。
うーん、個人的には"A\t\t".split → [ "A" ,"",""]になってくれたほうがうれしい気がするのだが。

今回は
io = open(ARGV[0])
line=nil
while line=io.gets
  line.chomp!
  s = line.split(/\t/)
  print s,join("\t")
  print( "\t" * ( ARGV[1] - s.length ) )
  puts
end

で逃げた。
[PR]
by nora1962 | 2009-04-14 05:03 | PC

rubyで[BUG] Segmentation fault その後

ruby-pg-0.7.9.2008.10.13をVISTA環境でコンパイルするとDBIで使用できずに、[BUG] Segmentation faultが表示されて落ちる件のその後。

環境はVISTA SP1、VISUAL C++ 2008。

ためしにもう一台もっているPC( XP Pro )でVISUAL C++ 6.0でコンパイルしたpg.soを
「C:\ruby\lib\ruby\site_ruby\1.8\i386-msvcrt」にコピーしてみた。

ビンゴ!

DBIが動く。
ちなみにVISUAL C++ 2005でコンパイルしたpg.soではだめだった。

しかしVISUAL C++ 6.0 もうサポート終了だし、VISTAにインストールしようとすると「互換性」なんちゃらかちゃっらのメッセージが出てくる。正常にインストールできないみたいだ。

Ruby本体をOneClickInstaller版使っているのが悪いのかね。

しかし、Ruby本体をVisual C++ 2008でコンパイルする気にはさすがにならない。
とりあえず、Rubyの学習が目的なので現状でよしとする。
[PR]
by nora1962 | 2009-03-29 01:33 | PC